diff options
author | clamy <clamy@chromium.org> | 2015-11-20 06:55:49 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-20 14:56:37 +0000 |
commit | 94ca34e7e6c05e75f2c10a87b76a1839d96a1ebd (patch) | |
tree | 66f293a4e55da875afa0bc05e004c44bee3bf20b | |
parent | e0807cfe3196f5313211d8938c155f43ea2b416d (diff) | |
download | chromium_src-94ca34e7e6c05e75f2c10a87b76a1839d96a1ebd.zip chromium_src-94ca34e7e6c05e75f2c10a87b76a1839d96a1ebd.tar.gz chromium_src-94ca34e7e6c05e75f2c10a87b76a1839d96a1ebd.tar.bz2 |
Add a method in NavigationHandle to get the HttpResponseHeaders
This CL adds a method in NavigationHandle to get the HttpResponseHeaders,
received after a navigation has encountered a redirect or is ready to commit.
BUG=537634
Review URL: https://codereview.chromium.org/1409993018
Cr-Commit-Position: refs/heads/master@{#360818}
7 files changed, 120 insertions, 22 deletions
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 6ac5243..4fcb2c6c 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc @@ -159,6 +159,13 @@ bool NavigationHandleImpl::IsSamePage() { return is_same_page_; } +const net::HttpResponseHeaders* NavigationHandleImpl::GetResponseHeaders() { + DCHECK(state_ >= WILL_REDIRECT_REQUEST) + << "This accessor should only be called when the request encountered a " + "redirect or received a response"; + return response_headers_.get(); +} + bool NavigationHandleImpl::HasCommitted() { return state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE; } @@ -220,6 +227,7 @@ NavigationHandleImpl::CallWillRedirectRequestForTesting( NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER; WillRedirectRequest(new_url, new_method_is_post, new_referrer_url, new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders>(), base::Bind(&UpdateThrottleCheckResult, &result)); // Reset the callback to ensure it will not be called later. @@ -269,6 +277,7 @@ void NavigationHandleImpl::WillRedirectRequest( bool new_method_is_post, const GURL& new_referrer_url, bool new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders> response_headers, const ThrottleChecksFinishedCallback& callback) { // Update the navigation parameters. url_ = new_url; @@ -276,6 +285,7 @@ void NavigationHandleImpl::WillRedirectRequest( sanitized_referrer_.url = new_referrer_url; sanitized_referrer_ = Referrer::SanitizeForRequest(url_, sanitized_referrer_); is_external_protocol_ = new_is_external_protocol; + response_headers_ = response_headers; state_ = WILL_REDIRECT_REQUEST; complete_callback_ = callback; @@ -294,11 +304,19 @@ void NavigationHandleImpl::DidRedirectNavigation(const GURL& new_url) { } void NavigationHandleImpl::ReadyToCommitNavigation( - RenderFrameHostImpl* render_frame_host) { - CHECK(!render_frame_host_); + RenderFrameHostImpl* render_frame_host, + scoped_refptr<net::HttpResponseHeaders> response_headers) { + DCHECK(!render_frame_host_); render_frame_host_ = render_frame_host; + response_headers_ = response_headers; state_ = READY_TO_COMMIT; - GetDelegate()->ReadyToCommitNavigation(this); + + // Only notify the WebContentsObservers when PlzNavigate is enabled, as + // |render_frame_host_| may be wrong in the case of transfer navigations. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation)) { + GetDelegate()->ReadyToCommitNavigation(this); + } } void NavigationHandleImpl::DidCommitNavigation( diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index 622512f..70fb99e 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h @@ -100,6 +100,12 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { NavigatorDelegate* GetDelegate() const; + // Returns the response headers for the request. This can only be accessed + // after a redirect was encountered or after the the navigation is ready to + // commit. It should not be modified, as modifications will not be reflected + // in the network stack. + const net::HttpResponseHeaders* GetResponseHeaders(); + void set_net_error_code(net::Error net_error_code) { net_error_code_ = net_error_code; } @@ -113,6 +119,12 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { is_transferring_ = is_transferring; } + // Updates the RenderFrameHost that is about to commit the navigation. This + // is used during transfer navigations. + void set_render_frame_host(RenderFrameHostImpl* render_frame_host) { + render_frame_host_ = render_frame_host; + } + // PlzNavigate ServiceWorkerNavigationHandle* service_worker_handle() const { return service_worker_handle_.get(); @@ -134,11 +146,13 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { // Called when the URLRequest will be redirected in the network stack. // |callback| will be called when all throttles check have completed. This // will allow the caller to cancel the navigation or let it proceed. - void WillRedirectRequest(const GURL& new_url, - bool new_method_is_post, - const GURL& new_referrer_url, - bool new_is_external_protocol, - const ThrottleChecksFinishedCallback& callback); + void WillRedirectRequest( + const GURL& new_url, + bool new_method_is_post, + const GURL& new_referrer_url, + bool new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders> response_headers, + const ThrottleChecksFinishedCallback& callback); // Called when the navigation was redirected. This will update the |url_| and // inform the delegate. @@ -147,7 +161,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { // Called when the navigation is ready to be committed in // |render_frame_host|. This will update the |state_| and inform the // delegate. - void ReadyToCommitNavigation(RenderFrameHostImpl* render_frame_host); + void ReadyToCommitNavigation( + RenderFrameHostImpl* render_frame_host, + scoped_refptr<net::HttpResponseHeaders> response_headers); // Called when the navigation was committed in |render_frame_host|. This will // update the |state_|. @@ -194,6 +210,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { net::Error net_error_code_; RenderFrameHostImpl* render_frame_host_; bool is_same_page_; + scoped_refptr<net::HttpResponseHeaders> response_headers_; // The state the navigation is in. State state_; diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc index cd2d0ec..ee999cb 100644 --- a/content/browser/frame_host/navigation_handle_impl_unittest.cc +++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc @@ -103,7 +103,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness { // It's safe to use base::Unretained since the NavigationHandle is owned by // the NavigationHandleImplTest. test_handle_->WillRedirectRequest( - GURL(), false, GURL(), false, + GURL(), false, GURL(), false, scoped_refptr<net::HttpResponseHeaders>(), base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); } diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index fbabed6..7c7dcd6 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc @@ -17,6 +17,7 @@ #include "content/public/browser/navigation_controller.h" #include "content/public/browser/stream_handle.h" #include "content/public/common/content_client.h" +#include "content/public/common/resource_response.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" #include "net/url_request/redirect_info.h" @@ -224,8 +225,6 @@ void NavigationRequest::CreateNavigationHandle() { void NavigationRequest::TransferNavigationHandleOwnership( RenderFrameHostImpl* render_frame_host) { render_frame_host->SetNavigationHandle(navigation_handle_.Pass()); - render_frame_host->navigation_handle()->ReadyToCommitNavigation( - render_frame_host); } void NavigationRequest::OnRequestRedirected( @@ -243,7 +242,7 @@ void NavigationRequest::OnRequestRedirected( // TODO(clamy): pass the real value for |is_external_protocol| if needed. navigation_handle_->WillRedirectRequest( common_params_.url, begin_params_.method == "POST", - common_params_.referrer.url, false, + common_params_.referrer.url, false, response->head.headers, base::Bind(&NavigationRequest::OnRedirectChecksComplete, base::Unretained(this))); } diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 0b83a77..742445a 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc @@ -151,6 +151,8 @@ void NavigatorImpl::DidStartProvisionalLoad( // DidStartProvisionalLoad should not correspond to a new navigation. DCHECK_EQ(url, render_frame_host->navigation_handle()->GetURL()); render_frame_host->navigation_handle()->set_is_transferring(false); + render_frame_host->navigation_handle()->set_render_frame_host( + render_frame_host); return; } @@ -749,6 +751,8 @@ void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, render_frame_host, navigation_request->common_params().url); navigation_request->TransferNavigationHandleOwnership(render_frame_host); + render_frame_host->navigation_handle()->ReadyToCommitNavigation( + render_frame_host, response ? response->head.headers : nullptr); render_frame_host->CommitNavigation(response, body.Pass(), navigation_request->common_params(), navigation_request->request_params()); @@ -779,6 +783,8 @@ void NavigatorImpl::FailedNavigation(FrameTreeNode* frame_tree_node, render_frame_host, navigation_request->common_params().url); navigation_request->TransferNavigationHandleOwnership(render_frame_host); + render_frame_host->navigation_handle()->ReadyToCommitNavigation( + render_frame_host, scoped_refptr<net::HttpResponseHeaders>()); render_frame_host->FailedNavigation(navigation_request->common_params(), navigation_request->request_params(), has_stale_copy_in_cache, error_code); diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc index efb3ac9..44fd0c1 100644 --- a/content/browser/loader/navigation_resource_throttle.cc +++ b/content/browser/loader/navigation_resource_throttle.cc @@ -59,13 +59,15 @@ void CheckWillStartRequestOnUIThread(UIChecksPerformedCallback callback, is_external_protocol, base::Bind(&SendCheckResultToIOThread, callback)); } -void CheckWillRedirectRequestOnUIThread(UIChecksPerformedCallback callback, - int render_process_id, - int render_frame_host_id, - const GURL& new_url, - bool new_method_is_post, - const GURL& new_referrer_url, - bool new_is_external_protocol) { +void CheckWillRedirectRequestOnUIThread( + UIChecksPerformedCallback callback, + int render_process_id, + int render_frame_host_id, + const GURL& new_url, + bool new_method_is_post, + const GURL& new_referrer_url, + bool new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders> headers) { DCHECK_CURRENTLY_ON(BrowserThread::UI); RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); @@ -86,10 +88,28 @@ void CheckWillRedirectRequestOnUIThread(UIChecksPerformedCallback callback, ->FilterURL(false, &new_validated_url); navigation_handle->WillRedirectRequest( new_validated_url, new_method_is_post, new_referrer_url, - new_is_external_protocol, + new_is_external_protocol, headers, base::Bind(&SendCheckResultToIOThread, callback)); } +void WillProcessResponseOnUIThread( + int render_process_id, + int render_frame_host_id, + scoped_refptr<net::HttpResponseHeaders> headers) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RenderFrameHostImpl* render_frame_host = + RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); + if (!render_frame_host) + return; + + NavigationHandleImpl* navigation_handle = + render_frame_host->navigation_handle(); + if (!navigation_handle) + return; + + navigation_handle->ReadyToCommitNavigation(render_frame_host, headers); +} + } // namespace NavigationResourceThrottle::NavigationResourceThrottle(net::URLRequest* request) @@ -98,6 +118,7 @@ NavigationResourceThrottle::NavigationResourceThrottle(net::URLRequest* request) NavigationResourceThrottle::~NavigationResourceThrottle() {} void NavigationResourceThrottle::WillStartRequest(bool* defer) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); if (!info) return; @@ -128,6 +149,7 @@ void NavigationResourceThrottle::WillStartRequest(bool* defer) { void NavigationResourceThrottle::WillRedirectRequest( const net::RedirectInfo& redirect_info, bool* defer) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); if (!info) return; @@ -144,15 +166,50 @@ void NavigationResourceThrottle::WillRedirectRequest( UIChecksPerformedCallback callback = base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed, weak_ptr_factory_.GetWeakPtr()); + + // Send the redirect info to the NavigationHandle on the UI thread. + // Note: to avoid threading issues, a copy of the HttpResponseHeaders is sent + // in lieu of the original. + scoped_refptr<net::HttpResponseHeaders> response_headers; + if (request_->response_headers()) { + response_headers = new net::HttpResponseHeaders( + request_->response_headers()->raw_headers()); + } + BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&CheckWillRedirectRequestOnUIThread, callback, render_process_id, render_frame_id, redirect_info.new_url, redirect_info.new_method == "POST", - GURL(redirect_info.new_referrer), new_is_external_protocol)); + GURL(redirect_info.new_referrer), new_is_external_protocol, + response_headers)); *defer = true; } +void NavigationResourceThrottle::WillProcessResponse(bool* defer) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); + if (!info) + return; + + int render_process_id, render_frame_id; + if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) + return; + + // Send a copy of the response headers to the NavigationHandle on the UI + // thread. + scoped_refptr<net::HttpResponseHeaders> response_headers; + if (request_->response_headers()) { + response_headers = new net::HttpResponseHeaders( + request_->response_headers()->raw_headers()); + } + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&WillProcessResponseOnUIThread, render_process_id, + render_frame_id, response_headers)); +} + const char* NavigationResourceThrottle::GetNameForLogging() const { return "NavigationResourceThrottle"; } diff --git a/content/browser/loader/navigation_resource_throttle.h b/content/browser/loader/navigation_resource_throttle.h index e46b59d..753d99b 100644 --- a/content/browser/loader/navigation_resource_throttle.h +++ b/content/browser/loader/navigation_resource_throttle.h @@ -28,6 +28,7 @@ class NavigationResourceThrottle : public ResourceThrottle { void WillStartRequest(bool* defer) override; void WillRedirectRequest(const net::RedirectInfo& redirect_info, bool* defer) override; + void WillProcessResponse(bool* defer) override; const char* GetNameForLogging() const override; private: |