blob: e9cba4a2ac460439564a95e1a57dd39c28829f1c [file] [log] [blame]
// Copyright 2014 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 CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_H_
#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_H_
#include <memory>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
#include "content/common/navigation_params.h"
#include "content/common/navigation_params.mojom.h"
#include "content/common/navigation_subresource_loader_params.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/common/previews_state.h"
namespace content {
class FrameNavigationEntry;
class FrameTreeNode;
class NavigationControllerImpl;
class NavigationHandleImpl;
class NavigationURLLoader;
class NavigationData;
class ResourceRequestBody;
class SiteInstanceImpl;
class StreamHandle;
struct SubresourceLoaderParams;
// PlzNavigate
// A UI thread object that owns a navigation request until it commits. It
// ensures the UI thread can start a navigation request in the
// ResourceDispatcherHost (that lives on the IO thread).
// TODO(clamy): Describe the interactions between the UI and IO thread during
// the navigation following its refactoring.
class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
public:
// Keeps track of the various stages of a NavigationRequest.
enum NavigationState {
// Initial state.
NOT_STARTED = 0,
// Waiting for a BeginNavigation IPC from the renderer in a
// browser-initiated navigation. If there is no live renderer when the
// request is created, this stage is skipped.
WAITING_FOR_RENDERER_RESPONSE,
// The request was sent to the IO thread.
STARTED,
// The response started on the IO thread and is ready to be committed. This
// is one of the two final states for the request.
RESPONSE_STARTED,
// The request failed on the IO thread and an error page should be
// displayed. This is one of the two final states for the request.
FAILED,
};
// The SiteInstance currently associated with the navigation. Note that the
// final value will only be known when the response is received, or the
// navigation fails, as server redirects can modify the SiteInstance to use
// for the navigation.
enum class AssociatedSiteInstanceType {
NONE = 0,
CURRENT,
SPECULATIVE,
};
// Creates a request for a browser-intiated navigation.
static std::unique_ptr<NavigationRequest> CreateBrowserInitiated(
FrameTreeNode* frame_tree_node,
const GURL& dest_url,
const Referrer& dest_referrer,
const FrameNavigationEntry& frame_entry,
const NavigationEntryImpl& entry,
FrameMsg_Navigate_Type::Value navigation_type,
PreviewsState previews_state,
bool is_same_document_history_load,
bool is_history_navigation_in_new_child,
const scoped_refptr<ResourceRequestBody>& post_body,
const base::TimeTicks& navigation_start,
NavigationControllerImpl* controller);
// Creates a request for a renderer-intiated navigation.
// Note: |body| is sent to the IO thread when calling BeginNavigation, and
// should no longer be manipulated afterwards on the UI thread.
// TODO(clamy): see if ResourceRequestBody could be un-refcounted to avoid
// threading subtleties.
static std::unique_ptr<NavigationRequest> CreateRendererInitiated(
FrameTreeNode* frame_tree_node,
NavigationEntryImpl* entry,
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
int current_history_list_offset,
int current_history_list_length,
bool override_user_agent);
~NavigationRequest() override;
// Called on the UI thread by the Navigator to start the navigation.
// The NavigationRequest can be deleted while BeginNavigation() is called.
void BeginNavigation();
const CommonNavigationParams& common_params() const { return common_params_; }
const mojom::BeginNavigationParams* begin_params() const {
return begin_params_.get();
}
const RequestNavigationParams& request_params() const {
return request_params_;
}
// Updates the navigation start time.
void set_navigation_start_time(const base::TimeTicks& time) {
common_params_.navigation_start = time;
}
NavigationURLLoader* loader_for_testing() const { return loader_.get(); }
NavigationState state() const { return state_; }
FrameTreeNode* frame_tree_node() const { return frame_tree_node_; }
SiteInstanceImpl* source_site_instance() const {
return source_site_instance_.get();
}
SiteInstanceImpl* dest_site_instance() const {
return dest_site_instance_.get();
}
RestoreType restore_type() const { return restore_type_; };
bool is_view_source() const { return is_view_source_; };
int bindings() const { return bindings_; };
bool browser_initiated() const { return browser_initiated_ ; }
bool from_begin_navigation() const { return from_begin_navigation_; }
AssociatedSiteInstanceType associated_site_instance_type() const {
return associated_site_instance_type_;
}
void set_associated_site_instance_type(AssociatedSiteInstanceType type) {
associated_site_instance_type_ = type;
}
NavigationHandleImpl* navigation_handle() const {
return navigation_handle_.get();
}
int net_error() { return net_error_; }
void SetWaitingForRendererResponse();
// Creates a NavigationHandle. This should be called after any previous
// NavigationRequest for the FrameTreeNode has been destroyed.
void CreateNavigationHandle();
// Transfers the ownership of the NavigationHandle to |render_frame_host|.
// This should be called when the navigation is ready to commit, because the
// NavigationHandle outlives the NavigationRequest. The NavigationHandle's
// lifetime is the entire navigation, while the NavigationRequest is
// destroyed when a navigation is ready for commit.
void TransferNavigationHandleOwnership(
RenderFrameHostImpl* render_frame_host);
void set_on_start_checks_complete_closure_for_testing(
const base::Closure& closure) {
on_start_checks_complete_closure_ = closure;
}
int nav_entry_id() const { return nav_entry_id_; }
// For automation driver-initiated navigations over the devtools protocol,
// |devtools_navigation_token_| is used to tag the navigation. This navigation
// token is then sent into the renderer and lands on the DocumentLoader. That
// way subsequent Blink-level frame lifecycle events can be associated with
// the concrete navigation.
// - The value should not be sent back to the browser.
// - The value on DocumentLoader may be generated in the renderer in some
// cases, and thus shouldn't be trusted.
// TODO(crbug.com/783506): Replace devtools navigation token with the generic
// navigation token that can be passed from renderer to the browser.
const base::UnguessableToken& devtools_navigation_token() const {
return devtools_navigation_token_;
}
private:
// This enum describes the result of a Content Security Policy (CSP) check for
// the request.
enum ContentSecurityPolicyCheckResult {
// The request should be allowed to continue. PASSED could mean that the
// request did not violate any CSP, or that it violated a report-only CSP.
CONTENT_SECURITY_POLICY_CHECK_PASSED,
// The request should be blocked because it violated an enforced CSP.
CONTENT_SECURITY_POLICY_CHECK_FAILED,
};
NavigationRequest(FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
const RequestNavigationParams& request_params,
bool browser_initiated,
bool from_begin_navigation,
const FrameNavigationEntry* frame_navigation_entry,
const NavigationEntryImpl* navitation_entry);
// NavigationURLLoaderDelegate implementation.
void OnRequestRedirected(
const net::RedirectInfo& redirect_info,
const scoped_refptr<ResourceResponse>& response) override;
void OnResponseStarted(
const scoped_refptr<ResourceResponse>& response,
mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
std::unique_ptr<StreamHandle> body,
const net::SSLInfo& ssl_info,
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& request_id,
bool is_download,
bool is_stream,
base::Optional<SubresourceLoaderParams> subresource_loader_params)
override;
void OnRequestFailed(bool has_stale_copy_in_cache,
int net_error,
const base::Optional<net::SSLInfo>& ssl_info) override;
void OnRequestStarted(base::TimeTicks timestamp) override;
// A version of OnRequestFailed() that allows skipping throttles, to be used
// when a request failed due to a throttle result itself.
void OnRequestFailedInternal(bool has_stale_copy_in_cache,
int net_error,
const base::Optional<net::SSLInfo>& ssl_info,
bool skip_throttles);
// Called when the NavigationThrottles have been checked by the
// NavigationHandle.
void OnStartChecksComplete(NavigationThrottle::ThrottleCheckResult result);
void OnRedirectChecksComplete(NavigationThrottle::ThrottleCheckResult result);
void OnFailureChecksComplete(RenderFrameHostImpl* render_frame_host,
NavigationThrottle::ThrottleCheckResult result);
void OnWillProcessResponseChecksComplete(
NavigationThrottle::ThrottleCheckResult result);
// Called either by OnFailureChecksComplete() or OnRequestFailed() directly.
// |error_page_content| contains the content of the error page (i.e. flattened
// HTML, JS, CSS).
void CommitErrorPage(RenderFrameHostImpl* render_frame_host,
const base::Optional<std::string>& error_page_content);
// Have a RenderFrameHost commit the navigation. The NavigationRequest will
// be destroyed after this call.
void CommitNavigation();
// Check whether a request should be allowed to continue or should be blocked
// because it violates a CSP. This method can have two side effects:
// - If a CSP is configured to send reports and the request violates the CSP,
// a report will be sent.
// - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
// configured to upgrade insecure requests.
ContentSecurityPolicyCheckResult CheckContentSecurityPolicyFrameSrc(
bool is_redirect);
// This enum describes the result of the credentialed subresource check for
// the request.
enum class CredentialedSubresourceCheckResult {
ALLOW_REQUEST,
BLOCK_REQUEST,
};
// Chrome blocks subresource requests whose URLs contain embedded credentials
// (e.g. `https://user:[email protected]/page.html`). Check whether the
// request should be allowed to continue or should be blocked.
CredentialedSubresourceCheckResult CheckCredentialedSubresource() const;
// This enum describes the result of the legacy protocol check for
// the request.
enum class LegacyProtocolInSubresourceCheckResult {
ALLOW_REQUEST,
BLOCK_REQUEST,
};
// Block subresources requests that target "legacy" protocol (like "ftp") when
// the main document is not served from a "legacy" protocol.
LegacyProtocolInSubresourceCheckResult CheckLegacyProtocolInSubresource()
const;
FrameTreeNode* frame_tree_node_;
// Initialized on creation of the NavigationRequest. Sent to the renderer when
// the navigation is ready to commit.
// Note: When the navigation is ready to commit, the url in |common_params|
// will be set to the final navigation url, obtained after following all
// redirects.
// Note: |common_params_| and |begin_params_| are not const as they can be
// modified during redirects.
// Note: |request_params_| is not const because service_worker_provider_id
// and should_create_service_worker will be set in OnResponseStarted.
CommonNavigationParams common_params_;
mojom::BeginNavigationParamsPtr begin_params_;
RequestNavigationParams request_params_;
const bool browser_initiated_;
NavigationState state_;
std::unique_ptr<NavigationURLLoader> loader_;
// These next items are used in browser-initiated navigations to store
// information from the NavigationEntryImpl that is required after request
// creation time.
scoped_refptr<SiteInstanceImpl> source_site_instance_;
scoped_refptr<SiteInstanceImpl> dest_site_instance_;
RestoreType restore_type_;
bool is_view_source_;
int bindings_;
int nav_entry_id_ = 0;
// Whether the navigation should be sent to a renderer a process. This is
// true, except for 204/205 responses and downloads.
bool response_should_be_rendered_;
// The type of SiteInstance associated with this navigation.
AssociatedSiteInstanceType associated_site_instance_type_;
// Stores the SiteInstance created on redirects to check if there is an
// existing RenderProcessHost that can commit the navigation so that the
// renderer process is not deleted while the navigation is ongoing. If the
// SiteInstance was a brand new SiteInstance, it is not stored.
scoped_refptr<SiteInstance> speculative_site_instance_;
// Whether the NavigationRequest was created after receiving a BeginNavigation
// IPC. When true, main frame navigations should not commit in a different
// process (unless asked by the content/ embedder). When true, the renderer
// process expects to be notified if the navigation is aborted.
bool from_begin_navigation_;
std::unique_ptr<NavigationHandleImpl> navigation_handle_;
// Holds objects received from OnResponseStarted while the WillProcessResponse
// checks are performed by the NavigationHandle. Once the checks have been
// completed, these objects will be used to continue the navigation.
// The URLLoaderClientEndpointsPtr is used when the Network Service or
// NavigationMojoResponse is enabled. Otherwise the StreamHandle is used.
scoped_refptr<ResourceResponse> response_;
std::unique_ptr<StreamHandle> body_;
mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints_;
net::SSLInfo ssl_info_;
bool is_download_;
// Holds information for the navigation while the WillFailRequest
// checks are performed by the NavigationHandle.
bool has_stale_copy_in_cache_;
int net_error_;
base::Closure on_start_checks_complete_closure_;
// Used in the network service world to pass the subressource loader params
// to the renderer. Used by AppCache and ServiceWorker.
base::Optional<SubresourceLoaderParams> subresource_loader_params_;
// See comment on accessor.
base::UnguessableToken devtools_navigation_token_;
base::WeakPtrFactory<NavigationRequest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
};
} // namespace content
#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_H_