blob: 12fb37a114833dd4345028990d655fff01a682c2 [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.
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/values.h"
#import "ios/web/js_messaging/web_frames_manager_impl.h"
#import "ios/web/navigation/navigation_manager_delegate.h"
#import "ios/web/navigation/navigation_manager_impl.h"
#import "ios/web/public/navigation/web_state_policy_decider.h"
#import "ios/web/public/ui/java_script_dialog_callback.h"
#include "ios/web/public/ui/java_script_dialog_type.h"
#import "ios/web/public/web_state.h"
#import "ios/web/public/web_state_delegate.h"
#include "url/gurl.h"
@class CRWSessionStorage;
@class CRWWebController;
@protocol CRWWebViewProxy;
@class NSURLRequest;
@class NSURLResponse;
@protocol CRWWebViewNavigationProxy;
@class UIViewController;
namespace web {
class BrowserState;
struct ContextMenuParams;
struct FaviconURL;
class NavigationContextImpl;
class NavigationManager;
class SessionCertificatePolicyCacheImpl;
class WebFrame;
class WebUIIOS;
// Implementation of WebState.
// Generally mirrors //content's WebContents implementation.
// General notes on expected WebStateImpl ownership patterns:
// - Outside of tests, WebStateImpls are created
// (a) By @Tab, when creating a new Tab.
// (b) By @SessionWindow, when decoding a saved session.
// (c) By the Copy() method, below, used when marshalling a session
// in preparation for saving.
// - WebControllers are the eventual long-term owners of WebStateImpls.
// - SessionWindows are transient owners, passing ownership into WebControllers
// during session restore, and discarding owned copies of WebStateImpls after
// writing them out for session saves.
class WebStateImpl : public WebState,
public NavigationManagerDelegate,
public WebFramesManagerDelegate {
// Constructor for WebStateImpls created for new sessions.
explicit WebStateImpl(const CreateParams& params);
// Constructor for WebStatesImpls created for deserialized sessions
WebStateImpl(const CreateParams& params, CRWSessionStorage* session_storage);
~WebStateImpl() override;
// Gets/Sets the CRWWebController that backs this object.
CRWWebController* GetWebController();
void SetWebController(CRWWebController* web_controller);
// Notifies the observers that a navigation has started.
void OnNavigationStarted(web::NavigationContextImpl* context);
// Notifies the observers that a navigation was redirected.
void OnNavigationRedirected(web::NavigationContextImpl* context);
// Notifies the observers that a navigation has finished. For same-document
// navigations notifies the observers about favicon URLs update using
// candidates received in OnFaviconUrlUpdated.
void OnNavigationFinished(web::NavigationContextImpl* context);
// Called when current window's canGoBack / canGoForward state was changed.
void OnBackForwardStateChanged();
// Called when page title was changed.
void OnTitleChanged();
// Notifies the observers that the render process was terminated.
void OnRenderProcessGone();
// Called when a script command is received.
void OnScriptCommandReceived(const std::string& command,
const base::DictionaryValue& value,
const GURL& page_url,
bool user_is_interacting,
web::WebFrame* sender_frame);
void SetIsLoading(bool is_loading);
// Called when a page is loaded. Must be called only once per page.
void OnPageLoaded(const GURL& url, bool load_success);
// Called when new FaviconURL candidates are received.
void OnFaviconUrlUpdated(const std::vector<FaviconURL>& candidates);
// Returns the NavigationManager for this WebState.
const NavigationManagerImpl& GetNavigationManagerImpl() const;
NavigationManagerImpl& GetNavigationManagerImpl();
// Returns the associated WebFramesManagerImpl.
const WebFramesManagerImpl& GetWebFramesManagerImpl() const;
WebFramesManagerImpl& GetWebFramesManagerImpl();
// Returns the SessionCertificatePolicyCacheImpl for this WebStateImpl.
const SessionCertificatePolicyCacheImpl&
GetSessionCertificatePolicyCacheImpl() const;
SessionCertificatePolicyCacheImpl& GetSessionCertificatePolicyCacheImpl();
// Creates a WebUI page for the given url, owned by this object.
void CreateWebUI(const GURL& url);
// Clears any current WebUI. Should be called when the page changes.
// TODO(stuartmorgan): Remove once more logic is moved from WebController
// into this class.
void ClearWebUI();
// Returns true if there is a WebUI active.
bool HasWebUI();
// Explicitly sets the MIME type, overwriting any MIME type that was set by
// headers. Note that this should be called after OnNavigationCommitted, as
// that is the point where MIME type is set from HTTP headers.
void SetContentsMimeType(const std::string& mime_type);
// Returns whether the navigation corresponding to |request| should be allowed
// to continue by asking its policy deciders. Defaults to
// PolicyDecision::Allow().
WebStatePolicyDecider::PolicyDecision ShouldAllowRequest(
NSURLRequest* request,
const WebStatePolicyDecider::RequestInfo& request_info);
// Decides whether the navigation corresponding to |response| should be
// allowed to continue by asking its policy deciders, and calls |callback|
// with the decision. Defaults to PolicyDecision::Allow(). If at least one
// policy decider's decision is PolicyDecision::Cancel(), the final result is
// PolicyDecision::Cancel(). Otherwise, if at least one policy decider's
// decision is PolicyDecision::CancelAndDisplayError(), the final result is
// PolicyDecision::CancelAndDisplayError(), with the error corresponding to
// the first PolicyDecision::CancelAndDisplayError() result that was received.
void ShouldAllowResponse(
NSURLResponse* response,
bool for_main_frame,
base::OnceCallback<void(WebStatePolicyDecider::PolicyDecision)> callback);
// Determines whether the given link with |link_url| should show a preview on
// force touch.
bool ShouldPreviewLink(const GURL& link_url);
// Called when the user performs a peek action on a link with |link_url| with
// force touch. Returns a view controller shown as a pop-up. Uses Webkit's
// default preview behavior when it returns nil.
UIViewController* GetPreviewingViewController(const GURL& link_url);
// Called when the user performs a pop action on the preview on force touch.
// |previewing_view_controller| is the view controller that is popped.
// It should display |previewing_view_controller| inside the app.
void CommitPreviewingViewController(
UIViewController* previewing_view_controller);
// Returns the UIView used to contain the WebView for sizing purposes. Can be
// nil.
UIView* GetWebViewContainer();
// WebFramesManagerDelegate.
void OnWebFrameAvailable(web::WebFrame* frame) override;
void OnWebFrameUnavailable(web::WebFrame* frame) override;
// WebState:
Getter CreateDefaultGetter() override;
OnceGetter CreateDefaultOnceGetter() override;
WebStateDelegate* GetDelegate() override;
void SetDelegate(WebStateDelegate* delegate) override;
bool IsWebUsageEnabled() const override;
void SetWebUsageEnabled(bool enabled) override;
UIView* GetView() override;
void DidCoverWebContent() override;
void DidRevealWebContent() override;
void WasShown() override;
void WasHidden() override;
void SetKeepRenderProcessAlive(bool keep_alive) override;
BrowserState* GetBrowserState() const override;
void OpenURL(const WebState::OpenURLParams& params) override;
void Stop() override;
const NavigationManager* GetNavigationManager() const override;
NavigationManager* GetNavigationManager() override;
const WebFramesManager* GetWebFramesManager() const override;
WebFramesManager* GetWebFramesManager() override;
const SessionCertificatePolicyCache* GetSessionCertificatePolicyCache()
const override;
SessionCertificatePolicyCache* GetSessionCertificatePolicyCache() override;
CRWSessionStorage* BuildSessionStorage() override;
CRWJSInjectionReceiver* GetJSInjectionReceiver() const override;
void LoadData(NSData* data, NSString* mime_type, const GURL& url) override;
void ExecuteJavaScript(const std::u16string& javascript) override;
void ExecuteJavaScript(const std::u16string& javascript,
JavaScriptResultCallback callback) override;
void ExecuteUserJavaScript(NSString* javaScript) override;
const std::string& GetContentsMimeType() const override;
bool ContentIsHTML() const override;
const std::u16string& GetTitle() const override;
bool IsLoading() const override;
double GetLoadingProgress() const override;
bool IsCrashed() const override;
bool IsVisible() const override;
bool IsEvicted() const override;
bool IsBeingDestroyed() const override;
const GURL& GetVisibleURL() const override;
const GURL& GetLastCommittedURL() const override;
GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const override;
base::CallbackListSubscription AddScriptCommandCallback(
const ScriptCommandCallback& callback,
const std::string& command_prefix) override;
id<CRWWebViewProxy> GetWebViewProxy() const override;
void DidChangeVisibleSecurityState() override;
InterfaceBinder* GetInterfaceBinderForMainFrame() override;
bool HasOpener() const override;
void SetHasOpener(bool has_opener) override;
bool CanTakeSnapshot() const override;
void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override;
void CreateFullPagePdf(base::OnceCallback<void(NSData*)> callback) override;
void AddObserver(WebStateObserver* observer) override;
void RemoveObserver(WebStateObserver* observer) override;
void CloseWebState() override;
// Returns the UserAgent that should be used to load the |url| if it is a new
// navigation. This will be Mobile or Desktop.
UserAgentType GetUserAgentForNextNavigation(const GURL& url);
// Returns the UserAgent type actually used by this WebState, mostly use for
// restoration.
UserAgentType GetUserAgentForSessionRestoration() const;
// Sets the UserAgent type that should be used by the WebState. If
// |user_agent| is AUTOMATIC, GetUserAgentForNextNavigation() will return
// MOBILE or DESKTOP based on the size class of the WebView. Otherwise, it
// will return |user_agent|.
// GetUserAgentForSessionRestoration() will always return |user_agent|.
void SetUserAgent(UserAgentType user_agent);
// Notifies the delegate that the load progress was updated.
void SendChangeLoadProgress(double progress);
// Notifies the delegate that a context menu needs handling.
void HandleContextMenu(const ContextMenuParams& params);
// Notifies the delegate that a Form Repost dialog needs to be presented.
void ShowRepostFormWarningDialog(base::OnceCallback<void(bool)> callback);
// Notifies the delegate that a JavaScript dialog needs to be presented.
void RunJavaScriptDialog(const GURL& origin_url,
JavaScriptDialogType java_script_dialog_type,
NSString* message_text,
NSString* default_prompt_text,
DialogClosedCallback callback);
// Instructs the delegate to create a new web state. Called when this WebState
// wants to open a new window. |url| is the URL of the new window;
// |opener_url| is the URL of the page which requested a window to be open;
// |initiated_by_user| is true if action was caused by the user.
WebState* CreateNewWebState(const GURL& url,
const GURL& opener_url,
bool initiated_by_user);
// Notifies the delegate that request receives an authentication challenge
// and is unable to respond using cached credentials.
void OnAuthRequired(NSURLProtectionSpace* protection_space,
NSURLCredential* proposed_credential,
WebStateDelegate::AuthCallback callback);
// Cancels all dialogs associated with this web_state.
void CancelDialogs();
// NavigationManagerDelegate:
void ClearDialogs() override;
void RecordPageStateInNavigationItem() override;
void LoadCurrentItem(NavigationInitiationType type) override;
void LoadIfNecessary() override;
void Reload() override;
void OnNavigationItemCommitted(NavigationItem* item) override;
WebState* GetWebState() override;
void SetWebStateUserAgent(UserAgentType user_agent_type) override;
id<CRWWebViewNavigationProxy> GetWebViewNavigationProxy() const override;
void GoToBackForwardListItem(WKBackForwardListItem* wk_item,
NavigationItem* item,
NavigationInitiationType type,
bool has_user_gesture) override;
void RemoveWebView() override;
NavigationItemImpl* GetPendingItem() override;
void AddPolicyDecider(WebStatePolicyDecider* decider) override;
void RemovePolicyDecider(WebStatePolicyDecider* decider) override;
// The SessionStorageBuilder functions require access to private variables of
// WebStateImpl.
friend SessionStorageBuilder;
// Called when a dialog presented by the JavaScriptDialogPresenter is
// dismissed. |callback| is the callback provided to RunJavaScriptDialog(),
// and is executed with |success| and |user_input|.
// This is defined as a static function taking WeakPtr to WebStateImpl instead
// of an instance method of WebStateImpl. This is to guarantee that |callback|
// is called even when JavaScriptDialogClosed() is called after WebStateImpl
// is destructed. Otherwise WKWebView raises NSInternalInconsistencyException.
static void JavaScriptDialogClosed(base::WeakPtr<WebStateImpl> weak_web_state,
DialogClosedCallback callback,
bool success,
NSString* user_input);
// Creates a WebUIIOS object for |url| that is owned by the caller. Returns
// nullptr if |url| does not correspond to a WebUI page.
std::unique_ptr<web::WebUIIOS> CreateWebUIIOS(const GURL& url);
// Returns true if |web_controller_| has been set.
bool Configured() const;
// Restores session history into the navigation manager.
void RestoreSessionStorage(CRWSessionStorage* session_storage);
// Delegate, not owned by this object.
WebStateDelegate* delegate_;
// Stores whether the web state is currently loading a page.
bool is_loading_;
// Stores whether the web state is currently being destroyed.
bool is_being_destroyed_;
// The CRWWebController that backs this object.
CRWWebController* web_controller_;
// The NavigationManagerImpl that stores session info for this WebStateImpl.
std::unique_ptr<NavigationManagerImpl> navigation_manager_;
// The associated WebFramesManagerImpl.
WebFramesManagerImpl web_frames_manager_;
// The SessionCertificatePolicyCacheImpl that stores the certificate policy
// information for this WebStateImpl.
std::unique_ptr<SessionCertificatePolicyCacheImpl> certificate_policy_cache_;
// |web::WebUIIOS| object for the current page if it is a WebUI page that
// uses the web-based WebUI framework, or nullptr otherwise.
std::unique_ptr<web::WebUIIOS> web_ui_;
// A list of observers notified when page state changes. Weak references.
base::ObserverList<WebStateObserver, true>::Unchecked observers_;
// All the WebStatePolicyDeciders asked for navigation decision. Weak
// references.
// WebStatePolicyDeciders are semantically different from observers (they
// modify the behavior of the WebState) but are used like observers in the
// code, hence the ObserverList.
base::ObserverList<WebStatePolicyDecider, true>::Unchecked policy_deciders_;
std::string mime_type_;
// Returned by reference.
std::u16string empty_string16_;
// Callbacks associated to command prefixes.
// Whether this WebState has an opener. See
// WebState::CreateParams::created_with_opener_ for more details.
bool created_with_opener_;
// The most recently restored session history that has not yet committed in
// the WKWebView. This is reset in OnNavigationItemCommitted().
CRWSessionStorage* restored_session_storage_;
// Favicons URLs received in OnFaviconUrlUpdated.
// WebStateObserver:FaviconUrlUpdated must be called for same-document
// navigations, so this cache will be used to avoid running expensive favicon
// fetching JavaScript.
std::vector<web::FaviconURL> cached_favicon_urls_;
// Whether a JavaScript dialog is currently being presented.
bool running_javascript_dialog_ = false;
// The InterfaceBinder exposed by WebStateImpl. Used to handle Mojo interface
// requests from the main frame.
InterfaceBinder interface_binder_{this};
UserAgentType user_agent_type_;
base::WeakPtrFactory<WebStateImpl> weak_factory_;
} // namespace web