blob: 45fa2cca10a43ed45b01fecf6319b3c0c73c9ceb [file] [log] [blame]
// Copyright 2013 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.
#ifndef IOS_WEB_NAVIGATION_NAVIGATION_MANAGER_IMPL_H_
#define IOS_WEB_NAVIGATION_NAVIGATION_MANAGER_IMPL_H_
#include <stddef.h>
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#import "ios/web/navigation/navigation_item_impl.h"
#import "ios/web/public/navigation_item_list.h"
#import "ios/web/public/navigation_manager.h"
#include "ios/web/public/reload_type.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
@class CRWSessionController;
namespace web {
class BrowserState;
class NavigationItem;
class NavigationManagerDelegate;
class SessionStorageBuilder;
// Name of UMA histogram to log the number of items Navigation Manager was
// requested to restore. 100 is logged when the number of navigation items is
// greater than 100. This is just a requested count and actual number of
// restored items can be smaller.
extern const char kRestoreNavigationItemCount[];
// Defines the ways how a pending navigation can be initiated.
enum class NavigationInitiationType {
// Navigation initiation type is only valid for pending navigations, use NONE
// if a navigation is already committed.
NONE = 0,
// Navigation was initiated by the browser by calling NavigationManager
// methods. Examples of methods which cause browser-initiated navigations
// include:
// * NavigationManager::Reload()
// * NavigationManager::GoBack()
// * NavigationManager::GoForward()
BROWSER_INITIATED,
// Navigation was initiated by renderer. Examples of renderer-initiated
// navigations include:
// * <a> link click
// * changing window.location.href
// * redirect via the <meta http-equiv="refresh"> tag
// * using window.history.pushState
RENDERER_INITIATED,
};
// Implementation of NavigationManager.
// Generally mirrors upstream's NavigationController.
class NavigationManagerImpl : public NavigationManager {
public:
NavigationManagerImpl();
~NavigationManagerImpl() override;
// Returns the most recent Committed Item that is not the result of a client
// or server-side redirect from the given Navigation Manager. Returns nullptr
// if there's an error condition on the input |nav_manager|, such as nullptr
// or no non-redirect items.
static NavigationItem* GetLastCommittedNonRedirectedItem(
const NavigationManager* nav_manager);
// Setters for NavigationManagerDelegate and BrowserState.
virtual void SetDelegate(NavigationManagerDelegate* delegate);
virtual void SetBrowserState(BrowserState* browser_state);
// Sets the CRWSessionController that backs this object.
// Keeps a strong reference to |session_controller|.
// This method should only be called when deserializing |session_controller|
// and joining it with its NavigationManager. Other cases should call
// InitializeSession() or Restore().
// TODO(stuartmorgan): Also move deserialization of CRWSessionControllers
// under the control of this class, and move the bulk of CRWSessionController
// logic into it.
virtual void SetSessionController(
CRWSessionController* session_controller) = 0;
// Initializes a new session history.
virtual void InitializeSession() = 0;
// Helper functions for notifying WebStateObservers of changes.
// TODO(stuartmorgan): Make these private once the logic triggering them moves
// into this layer.
virtual void OnNavigationItemsPruned(size_t pruned_item_count) = 0;
virtual void OnNavigationItemCommitted() = 0;
// Prepares for the deletion of WKWebView such as caching necessary data.
virtual void DetachFromWebView();
// Temporary accessors and content/ class pass-throughs.
// TODO(stuartmorgan): Re-evaluate this list once the refactorings have
// settled down.
virtual CRWSessionController* GetSessionController() const = 0;
// Adds a transient item with the given URL. A transient item will be
// discarded on any navigation.
virtual void AddTransientItem(const GURL& url) = 0;
// Adds a new item with the given url, referrer, navigation type, initiation
// type and user agent override option, making it the pending item. If pending
// item is the same as the current item, this does nothing. |referrer| may be
// nil if there isn't one. The item starts out as pending, and will be lost
// unless |-commitPendingItem| is called.
virtual void AddPendingItem(
const GURL& url,
const web::Referrer& referrer,
ui::PageTransition navigation_type,
NavigationInitiationType initiation_type,
UserAgentOverrideOption user_agent_override_option) = 0;
// Commits the pending item, if any.
virtual void CommitPendingItem() = 0;
// Returns the navigation index that differs from the current item (or pending
// item if it exists) by the specified |offset|, skipping redirect navigation
// items. The index returned is not guaranteed to be valid.
// TODO(crbug.com/661316): Make this method private once navigation code is
// moved from CRWWebController to NavigationManagerImpl.
virtual int GetIndexForOffset(int offset) const = 0;
// Returns the index of the previous item. Only used by SessionStorageBuilder.
virtual int GetPreviousItemIndex() const = 0;
// Sets the index of the previous item. Only used by SessionStorageBuilder.
virtual void SetPreviousItemIndex(int previous_item_index) = 0;
// Updates navigation history (if applicable) after pushState.
// TODO(crbug.com/783382): This is a legacy method to maintain backward
// compatibility for PageLoad stat. Remove this method once PageLoad no longer
// depend on WebStateObserver::DidStartLoading.
virtual void AddPushStateItemIfNecessary(const GURL& url,
NSString* state_object,
ui::PageTransition transition) = 0;
// Returns true after session restoration has started, until the first
// post-restore navigation is finished. Returns true when first post-restore
// navigation is started, even though technically session restoration is
// complete.
virtual bool IsRestoreSessionInProgress() const = 0;
// Resets the transient url rewriter list.
void RemoveTransientURLRewriters();
// Creates a NavigationItem using the given properties. Calling this method
// resets the transient URLRewriters cached in this instance.
// TODO(crbug.com/738020): This method is only used by CRWSessionController.
// Remove it after switching to WKBasedNavigationManagerImpl.
std::unique_ptr<NavigationItemImpl> CreateNavigationItem(
const GURL& url,
const Referrer& referrer,
ui::PageTransition transition,
NavigationInitiationType initiation_type);
// Updates the URL of the yet to be committed pending item. Useful for page
// redirects. Does nothing if there is no pending item.
void UpdatePendingItemUrl(const GURL& url) const;
// The current NavigationItem. During a pending navigation, returns the
// NavigationItem for that navigation. If a transient NavigationItem exists,
// this NavigationItem will be returned.
// TODO(crbug.com/661316): Make this private once all navigation code is moved
// out of CRWWebController.
NavigationItemImpl* GetCurrentItemImpl() const;
// Updates the pending or last committed navigation item after replaceState.
// TODO(crbug.com/783382): This is a legacy method to maintain backward
// compatibility for PageLoad stat. Remove this method once PageLoad no longer
// depend on WebStateObserver::DidStartLoading.
void UpdateCurrentItemForReplaceState(const GURL& url,
NSString* state_object);
// Same as GoToIndex(int), but allows renderer-initiated navigations and
// specifying whether or not the navigation is caused by the user gesture.
void GoToIndex(int index,
NavigationInitiationType initiation_type,
bool has_user_gesture);
// NavigationManager:
NavigationItem* GetLastCommittedItem() const final;
int GetLastCommittedItemIndex() const final;
NavigationItem* GetPendingItem() const final;
NavigationItem* GetTransientItem() const final;
void LoadURLWithParams(const NavigationManager::WebLoadParams&) override;
void AddTransientURLRewriter(BrowserURLRewriter::URLRewriter rewriter) final;
void GoToIndex(int index) final;
void Reload(ReloadType reload_type, bool check_for_reposts) final;
void ReloadWithUserAgentType(UserAgentType user_agent_type) final;
void LoadIfNecessary() override;
void AddRestoreCompletionCallback(base::OnceClosure callback) override;
// Implementation for corresponding NavigationManager getters.
virtual NavigationItemImpl* GetPendingItemInCurrentOrRestoredSession()
const = 0;
virtual NavigationItemImpl* GetTransientItemImpl() const = 0;
// Unlike GetLastCommittedItem(), this method does not return null during
// session restoration (and returns last known committed item instead).
virtual NavigationItemImpl* GetLastCommittedItemInCurrentOrRestoredSession()
const = 0;
// Unlike GetLastCommittedItemIndex(), this method does not return -1 during
// session restoration (and returns last known committed item index instead).
virtual int GetLastCommittedItemIndexInCurrentOrRestoredSession() const = 0;
// Identical to GetItemAtIndex() but returns the underlying NavigationItemImpl
// instead of the public NavigationItem interface.
virtual NavigationItemImpl* GetNavigationItemImplAtIndex(
size_t index) const = 0;
protected:
// The SessionStorageBuilder functions require access to private variables of
// NavigationManagerImpl.
friend SessionStorageBuilder;
// TODO(crbug.com/738020): Remove legacy code and merge
// WKBasedNavigationManager into this class after the navigation experiment.
// Checks whether or not two URLs differ only in the fragment.
static bool IsFragmentChangeNavigationBetweenUrls(const GURL& existing_url,
const GURL& new_url);
// Applies the user agent override to |pending_item|, or inherits the user
// agent of |inherit_from| if |user_agent_override_option| is INHERIT.
static void UpdatePendingItemUserAgentType(
UserAgentOverrideOption override_option,
const NavigationItem* inherit_from,
NavigationItem* pending_item);
// Must be called by subclasses before restoring |item_count| navigation
// items.
void WillRestore(size_t item_count);
// Creates a NavigationItem using the given properties, where |previous_url|
// is the URL of the navigation just prior to the current one. If
// |url_rewriters| is not nullptr, apply them before applying the permanent
// URL rewriters from BrowserState.
// TODO(crbug.com/738020): Make this private when WKBasedNavigationManagerImpl
// is merged into this class.
std::unique_ptr<NavigationItemImpl> CreateNavigationItemWithRewriters(
const GURL& url,
const Referrer& referrer,
ui::PageTransition transition,
NavigationInitiationType initiation_type,
const GURL& previous_url,
const std::vector<BrowserURLRewriter::URLRewriter>* url_rewriters) const;
// Returns the most recent NavigationItem with an URL that generates an HTTP
// request.
NavigationItem* GetLastCommittedItemWithUserAgentType() const;
// Subclass specific implementation to update session state.
virtual void FinishGoToIndex(int index,
NavigationInitiationType type,
bool has_user_gesture) = 0;
virtual void FinishReload();
virtual void FinishLoadURLWithParams();
// Returns true if the subclass uses placeholder URLs and this is such a URL.
virtual bool IsPlaceholderUrl(const GURL& url) const;
// The primary delegate for this manager.
NavigationManagerDelegate* delegate_;
// The BrowserState that is associated with this instance.
BrowserState* browser_state_;
// List of transient url rewriters added by |AddTransientURLRewriter()|.
std::vector<BrowserURLRewriter::URLRewriter> transient_url_rewriters_;
};
} // namespace web
#endif // IOS_WEB_NAVIGATION_NAVIGATION_MANAGER_IMPL_H_