Chromium Code Reviews| Index: content/browser/loader/navigation_url_loader_network_service.cc |
| diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc |
| index f32156a4074b47cda6e106d7ed12dbfde21c131b..36c6c984b870792d6e0c96fb72959c45c2cbfeb9 100644 |
| --- a/content/browser/loader/navigation_url_loader_network_service.cc |
| +++ b/content/browser/loader/navigation_url_loader_network_service.cc |
| @@ -6,6 +6,7 @@ |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| +#include "base/debug/stack_trace.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/trace_event/trace_event.h" |
| #include "content/browser/appcache/appcache_navigation_handle.h" |
| @@ -15,6 +16,7 @@ |
| #include "content/browser/loader/navigation_resource_handler.h" |
| #include "content/browser/loader/navigation_resource_throttle.h" |
| #include "content/browser/loader/navigation_url_loader_delegate.h" |
| +#include "content/browser/loader/url_loader_request_handler.h" |
| #include "content/browser/resource_context_impl.h" |
| #include "content/browser/service_worker/service_worker_navigation_handle.h" |
| #include "content/browser/service_worker/service_worker_navigation_handle_core.h" |
| @@ -54,72 +56,122 @@ WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) { |
| return WebContentsImpl::FromFrameTreeNode(frame_tree_node); |
| } |
| -void PrepareNavigationStartOnIO( |
| - std::unique_ptr<ResourceRequest> resource_request, |
| - ResourceContext* resource_context, |
| - ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
| - AppCacheNavigationHandleCore* appcache_handle_core, |
| - NavigationRequestInfo* request_info, |
| - mojom::URLLoaderFactoryPtrInfo factory_from_ui, |
| - scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter, |
| - const base::Callback<WebContents*(void)>& web_contents_getter, |
| - mojom::URLLoaderAssociatedRequest url_loader_request, |
| - mojom::URLLoaderClientPtr url_loader_client_to_pass, |
| - std::unique_ptr<service_manager::Connector> connector) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| - |
| - const ResourceType resource_type = request_info->is_main_frame |
| - ? RESOURCE_TYPE_MAIN_FRAME |
| - : RESOURCE_TYPE_SUB_FRAME; |
| - |
| - if (resource_request->request_body) { |
| - AttachRequestBodyBlobDataHandles(resource_request->request_body.get(), |
| - resource_context); |
| +} // namespace |
| + |
| +class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| + : public URLLoaderRequestHandler::Controller { |
| + public: |
| + URLLoaderRequestController(std::unique_ptr<ResourceRequest> resource_request, |
| + ResourceContext* resource_context) |
| + : resource_request_(std::move(resource_request)), |
| + resource_context_(resource_context) {} |
| + |
| + virtual ~URLLoaderRequestController() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + } |
| + |
| + void Start( |
| + ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
| + AppCacheNavigationHandleCore* appcache_handle_core, |
| + std::unique_ptr<NavigationRequestInfo> request_info, |
| + mojom::URLLoaderFactoryPtrInfo factory_for_webui, |
| + scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter, |
| + const base::Callback<WebContents*(void)>& web_contents_getter, |
| + mojom::URLLoaderAssociatedRequest url_loader_request, |
| + mojom::URLLoaderClientPtr url_loader_client_ptr, |
| + std::unique_ptr<service_manager::Connector> connector) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + const ResourceType resource_type = request_info->is_main_frame |
| + ? RESOURCE_TYPE_MAIN_FRAME |
| + : RESOURCE_TYPE_SUB_FRAME; |
| + |
| + if (resource_request_->request_body) { |
| + AttachRequestBodyBlobDataHandles(resource_request_->request_body.get(), |
| + resource_context_); |
| + } |
| + |
| + // Requests to WebUI scheme won't get redirected to/from other schemes |
| + // or be intercepted, so we just let it go here. |
|
michaeln
2017/05/26 01:28:31
nice clarifying change to rearrange the order
|
| + if (factory_for_webui.is_valid()) { |
| + fallback_factory_ptr_.Bind(std::move(factory_for_webui)); |
| + fallback_factory_ = fallback_factory_ptr_.get(); |
| + Restart(std::move(url_loader_request), std::move(url_loader_client_ptr)); |
| + return; |
| + } |
| + |
|
michaeln
2017/05/26 01:28:30
i think blob scheme handling will goes here too, m
|
| + DCHECK(handlers_.empty()); |
| + if (service_worker_navigation_handle_core) { |
| + RequestContextFrameType frame_type = |
| + request_info->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL |
| + : REQUEST_CONTEXT_FRAME_TYPE_NESTED; |
| + |
| + storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext( |
| + GetChromeBlobStorageContextForResourceContext(resource_context_)); |
| + std::unique_ptr<URLLoaderRequestHandler> service_worker_handler = |
| + ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( |
| + *resource_request_, resource_context_, |
| + service_worker_navigation_handle_core, blob_storage_context, |
| + request_info->begin_params.skip_service_worker, resource_type, |
| + request_info->begin_params.request_context_type, frame_type, |
| + request_info->are_ancestors_secure, |
| + request_info->common_params.post_data, web_contents_getter); |
| + if (service_worker_handler) |
| + handlers_.push_back(std::move(service_worker_handler)); |
| + } |
| + |
| + if (appcache_handle_core) { |
| + // TODO: add appcache code here. |
| + } |
| + |
| + DCHECK(!fallback_factory_); |
| + fallback_factory_ = url_loader_factory_getter->GetNetworkFactory()->get(); |
| + |
| + Restart(std::move(url_loader_request), std::move(url_loader_client_ptr)); |
| } |
| - mojom::URLLoaderFactoryPtr url_loader_factory_ptr; |
| - if (service_worker_navigation_handle_core) { |
| - RequestContextFrameType frame_type = |
| - request_info->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL |
| - : REQUEST_CONTEXT_FRAME_TYPE_NESTED; |
| - |
| - storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext( |
| - GetChromeBlobStorageContextForResourceContext(resource_context)); |
| - url_loader_factory_ptr = |
| - ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( |
| - *resource_request, resource_context, |
| - service_worker_navigation_handle_core, blob_storage_context, |
| - request_info->begin_params.skip_service_worker, resource_type, |
| - request_info->begin_params.request_context_type, frame_type, |
| - request_info->are_ancestors_secure, |
| - request_info->common_params.post_data, web_contents_getter); |
| + // This could be called multiple times. |
| + void Restart(mojom::URLLoaderAssociatedRequest url_loader_request, |
| + mojom::URLLoaderClientPtr url_loader_client_ptr) { |
| + handler_index_ = 0; |
| + DCHECK(url_loader_client_ptr.is_bound()); |
| + Forward(std::move(url_loader_request), std::move(url_loader_client_ptr)); |
| } |
| - // If we haven't gotten one from the above, then use the one the UI thread |
| - // gave us, or otherwise fallback to the default. |
| - mojom::URLLoaderFactory* factory; |
| - if (url_loader_factory_ptr) { |
| - factory = url_loader_factory_ptr.get(); |
| - } else { |
| - if (factory_from_ui.is_valid()) { |
| - url_loader_factory_ptr.Bind(std::move(factory_from_ui)); |
| - factory = url_loader_factory_ptr.get(); |
| - } else { |
| - if (appcache_handle_core) { |
| - factory = url_loader_factory_getter->GetAppCacheFactory()->get(); |
| - } else { |
| - factory = url_loader_factory_getter->GetNetworkFactory()->get(); |
| - } |
| + // This could be called multiple times. |
|
scottmg
2017/05/25 15:12:24
nit; comment that this is URLLoaderRH::Controller.
kinuko
2017/05/26 14:30:05
(Removed the Controller interface)
|
| + void Forward(mojom::URLLoaderAssociatedRequest url_loader_request, |
| + mojom::URLLoaderClientPtr url_loader_client_ptr) override { |
| + DCHECK(url_loader_client_ptr.is_bound()); |
| + |
| + if (handler_index_ < handlers_.size()) { |
| + handlers_[handler_index_++]->Start( |
| + *resource_request_, this, resource_context_, |
| + std::move(url_loader_request), std::move(url_loader_client_ptr)); |
| + return; |
| + } |
| + |
| + if (!url_loader_client_ptr.is_bound()) { |
| + base::debug::StackTrace trace; |
|
jam
2017/05/25 16:06:37
nit: is this still needed?
kinuko
2017/05/26 02:34:20
Of course not :)
kinuko
2017/05/26 14:30:05
Removed.
|
| + LOG(ERROR) << trace.ToString(); |
| } |
| + DCHECK_EQ(handlers_.size(), handler_index_); |
| + fallback_factory_->CreateLoaderAndStart( |
| + std::move(url_loader_request), 0 /* routing_id? */, 0 /* request_id? */, |
| + mojom::kURLLoadOptionSendSSLInfo, *resource_request_, |
| + std::move(url_loader_client_ptr)); |
| } |
| - factory->CreateLoaderAndStart( |
| - std::move(url_loader_request), 0 /* routing_id? */, 0 /* request_id? */, |
| - mojom::kURLLoadOptionSendSSLInfo, *resource_request, |
| - std::move(url_loader_client_to_pass)); |
| -} |
| + private: |
| + std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; |
| + size_t handler_index_ = 0; |
| -} // namespace |
| + std::unique_ptr<ResourceRequest> resource_request_; |
| + ResourceContext* resource_context_; |
| + |
| + mojom::URLLoaderFactoryPtr fallback_factory_ptr_; |
| + mojom::URLLoaderFactory* fallback_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); |
| +}; |
| NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| ResourceContext* resource_context, |
| @@ -129,36 +181,34 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
| AppCacheNavigationHandle* appcache_handle, |
| NavigationURLLoaderDelegate* delegate) |
| - : delegate_(delegate), |
| - binding_(this), |
| - request_info_(std::move(request_info)) { |
| + : delegate_(delegate), binding_(this) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( |
| "navigation", "Navigation timeToResponseStarted", this, |
| - request_info_->common_params.navigation_start, "FrameTreeNode id", |
| - request_info_->frame_tree_node_id); |
| + request_info->common_params.navigation_start, "FrameTreeNode id", |
| + request_info->frame_tree_node_id); |
| // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here. |
| auto new_request = base::MakeUnique<ResourceRequest>(); |
| - new_request->method = request_info_->common_params.method; |
| - new_request->url = request_info_->common_params.url; |
| - new_request->first_party_for_cookies = request_info_->first_party_for_cookies; |
| + new_request->method = request_info->common_params.method; |
| + new_request->url = request_info->common_params.url; |
| + new_request->first_party_for_cookies = request_info->first_party_for_cookies; |
| new_request->priority = net::HIGHEST; |
| // The code below to set fields like request_initiator, referrer, etc has |
| // been copied from ResourceDispatcherHostImpl. We did not refactor the |
| // common code into a function, because RDHI uses accessor functions on the |
| // URLRequest class to set these fields. whereas we use ResourceRequest here. |
| - new_request->request_initiator = request_info_->begin_params.initiator_origin; |
| - new_request->referrer = request_info_->common_params.referrer.url; |
| - new_request->referrer_policy = request_info_->common_params.referrer.policy; |
| - new_request->headers = request_info_->begin_params.headers; |
| + new_request->request_initiator = request_info->begin_params.initiator_origin; |
| + new_request->referrer = request_info->common_params.referrer.url; |
| + new_request->referrer_policy = request_info->common_params.referrer.policy; |
| + new_request->headers = request_info->begin_params.headers; |
| - int load_flags = request_info_->begin_params.load_flags; |
| + int load_flags = request_info->begin_params.load_flags; |
| load_flags |= net::LOAD_VERIFY_EV_CERT; |
| - if (request_info_->is_main_frame) |
| + if (request_info->is_main_frame) |
| load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; |
| // Sync loads should have maximum priority and should be the only |
| @@ -167,7 +217,9 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| new_request->load_flags = load_flags; |
| - new_request->request_body = request_info_->common_params.post_data.get(); |
| + new_request->request_body = request_info->common_params.post_data.get(); |
| + |
| + int frame_tree_node_id = request_info->frame_tree_node_id; |
| mojom::URLLoaderAssociatedRequest loader_associated_request = |
| mojo::MakeRequest(&url_loader_associated_ptr_); |
| @@ -181,33 +233,40 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| if (std::find(schemes.begin(), schemes.end(), new_request->url.scheme()) != |
| schemes.end()) { |
| FrameTreeNode* frame_tree_node = |
| - FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); |
| + FrameTreeNode::GloballyFindByID(frame_tree_node_id); |
| factory_ptr_info = GetWebUIURLLoader(frame_tree_node).PassInterface(); |
| } |
| g_next_request_id--; |
| + DCHECK(!request_controller_); |
| + request_controller_ = base::MakeUnique<URLLoaderRequestController>( |
| + std::move(new_request), resource_context); |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| - base::Bind(&PrepareNavigationStartOnIO, |
| - base::Passed(std::move(new_request)), resource_context, |
| - service_worker_navigation_handle |
| - ? service_worker_navigation_handle->core() |
| - : nullptr, |
| - appcache_handle ? appcache_handle->core() : nullptr, |
| - request_info_.get(), base::Passed(std::move(factory_ptr_info)), |
| - static_cast<StoragePartitionImpl*>(storage_partition) |
| - ->url_loader_factory_getter(), |
| - base::Bind(&GetWebContentsFromFrameTreeNodeID, |
| - request_info_->frame_tree_node_id), |
| - base::Passed(std::move(loader_associated_request)), |
| - base::Passed(std::move(url_loader_client_ptr_to_pass)), |
| - base::Passed(ServiceManagerConnection::GetForProcess() |
| - ->GetConnector() |
| - ->Clone()))); |
| + base::Bind( |
| + &URLLoaderRequestController::Start, |
| + base::Unretained(request_controller_.get()), |
| + service_worker_navigation_handle |
| + ? service_worker_navigation_handle->core() |
| + : nullptr, |
| + appcache_handle ? appcache_handle->core() : nullptr, |
| + base::Passed(std::move(request_info)), |
| + base::Passed(std::move(factory_ptr_info)), |
| + static_cast<StoragePartitionImpl*>(storage_partition) |
| + ->url_loader_factory_getter(), |
| + base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id), |
| + base::Passed(std::move(loader_associated_request)), |
| + base::Passed(std::move(url_loader_client_ptr_to_pass)), |
| + base::Passed(ServiceManagerConnection::GetForProcess() |
| + ->GetConnector() |
| + ->Clone()))); |
| } |
| -NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} |
| +NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() { |
| + BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, |
| + request_controller_.release()); |
| +} |
| void NavigationURLLoaderNetworkService::FollowRedirect() { |
| url_loader_associated_ptr_->FollowRedirect(); |
| @@ -232,6 +291,8 @@ void NavigationURLLoaderNetworkService::OnReceiveRedirect( |
| const net::RedirectInfo& redirect_info, |
| const ResourceResponseHead& head) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + // TODO(kinuko): Perform the necessary check and call |
| + // URLLoaderRequestController::Restart with the new URL?? |
| scoped_refptr<ResourceResponse> response(new ResourceResponse()); |
| response->head = head; |
| delegate_->OnRequestRedirected(redirect_info, response); |