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 fc4fb7ebb44b3d03035eeaf15baa705b2ea4cc4b..b51d3672e1dd295fccf30d715a06aa0baa832d29 100644 |
--- a/content/browser/loader/navigation_url_loader_network_service.cc |
+++ b/content/browser/loader/navigation_url_loader_network_service.cc |
@@ -10,10 +10,17 @@ |
#include "base/memory/ptr_util.h" |
#include "base/trace_event/trace_event.h" |
#include "content/browser/blob_storage/chrome_blob_storage_context.h" |
+#include "content/browser/frame_host/frame_tree_node.h" |
#include "content/browser/frame_host/navigation_request_info.h" |
#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/resource_context_impl.h" |
+#include "content/browser/service_worker/service_worker_context_wrapper.h" |
+#include "content/browser/service_worker/service_worker_navigation_handle.h" |
+#include "content/browser/service_worker/service_worker_navigation_handle_core.h" |
+#include "content/browser/service_worker/service_worker_request_handler.h" |
+#include "content/browser/web_contents/web_contents_impl.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/global_request_id.h" |
#include "content/public/browser/navigation_data.h" |
@@ -32,23 +39,60 @@ namespace content { |
namespace { |
static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky |
- g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; |
+ g_direct_network_url_loader_factory = LAZY_INSTANCE_INITIALIZER; |
-// This function is called on the IO thread for POST/PUT requests for |
-// attaching blob information to the request body. |
-void HandleRequestsWithBody( |
- std::unique_ptr<ResourceRequest> request, |
+using CompleteNavigationStart = |
+ base::Callback<void(mojom::URLLoaderFactoryPtrInfo, |
+ std::unique_ptr<ResourceRequest>)>; |
+ |
+void NavigationStartupWorkOnIO( |
+ std::unique_ptr<ResourceRequest> resource_request, |
ResourceContext* resource_context, |
- base::WeakPtr<NavigationURLLoaderNetworkService> url_loader) { |
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
+ bool skip_service_worker, |
+ ResourceType resource_type, |
+ RequestContextType request_context_type, |
+ RequestContextFrameType frame_type, |
+ bool is_parent_frame_secure, |
+ scoped_refptr<ResourceRequestBodyImpl> body, |
+ const base::Callback<WebContents*(void)>& web_contents_getter, |
+ CompleteNavigationStart complete_request) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- DCHECK(request->request_body.get()); |
+ DCHECK(service_worker_navigation_handle_core || |
+ resource_request->request_body.get()); |
+ |
+ mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; |
+ if (service_worker_navigation_handle_core) { |
+ storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext( |
+ GetChromeBlobStorageContextForResourceContext(resource_context)); |
+ url_loader_factory_ptr_info = |
+ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( |
+ *resource_request, resource_context, |
+ service_worker_navigation_handle_core, blob_storage_context, |
+ skip_service_worker, resource_type, request_context_type, |
+ frame_type, is_parent_frame_secure, body, web_contents_getter); |
+ } |
+ |
+ if (resource_request->request_body) { |
+ AttachRequestBodyBlobDataHandles(resource_request->request_body.get(), |
+ resource_context); |
+ } |
- AttachRequestBodyBlobDataHandles(request->request_body.get(), |
- resource_context); |
BrowserThread::PostTask( |
BrowserThread::UI, FROM_HERE, |
- base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, |
- url_loader, base::Passed(&request))); |
+ base::Bind(complete_request, |
+ base::Passed(std::move(url_loader_factory_ptr_info)), |
+ base::Passed(std::move(resource_request)))); |
+} |
+ |
+WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ FrameTreeNode* frame_tree_node = |
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id); |
+ if (!frame_tree_node) |
+ return nullptr; |
+ |
+ return WebContentsImpl::FromFrameTreeNode(frame_tree_node); |
} |
} // namespace |
@@ -58,7 +102,7 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
StoragePartition* storage_partition, |
std::unique_ptr<NavigationRequestInfo> request_info, |
std::unique_ptr<NavigationUIData> navigation_ui_data, |
- ServiceWorkerNavigationHandle* service_worker_handle, |
+ ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
AppCacheNavigationHandle* appcache_handle, |
NavigationURLLoaderDelegate* delegate) |
: delegate_(delegate), binding_(this), weak_factory_(this) { |
@@ -98,26 +142,48 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
new_request->load_flags = load_flags; |
new_request->request_body = request_info->common_params.post_data.get(); |
- if (new_request->request_body.get()) { |
- // The request body may need blob handles to be added to it. This |
- // functionality has to be invoked on the IO thread. |
+ |
+ ResourceType resource_type = request_info->is_main_frame |
+ ? RESOURCE_TYPE_MAIN_FRAME |
+ : RESOURCE_TYPE_SUB_FRAME; |
+ RequestContextFrameType frame_type = |
+ request_info->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL |
+ : REQUEST_CONTEXT_FRAME_TYPE_NESTED; |
+ |
+ // Determine where the request will be serviced. If there's work that needs to |
+ // be done on the IO thread due to Service Worker or POST body, then post to |
+ // the IO thread to have it do that work, and then continue on to |
+ // StartURLRequest. Otherwise, handle the request directly. |
+ const bool need_to_work_on_io = |
+ service_worker_navigation_handle || new_request->request_body; |
+ if (need_to_work_on_io) { |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
- base::Bind(&HandleRequestsWithBody, |
- base::Passed(&new_request), |
- resource_context, |
- weak_factory_.GetWeakPtr())); |
+ base::Bind( |
+ &NavigationStartupWorkOnIO, base::Passed(std::move(new_request)), |
+ resource_context, |
+ service_worker_navigation_handle |
+ ? service_worker_navigation_handle->core() |
+ : nullptr, |
+ 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, |
+ base::Bind(&GetWebContentsFromFrameTreeNodeID, |
+ request_info->frame_tree_node_id), |
+ base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, |
+ weak_factory_.GetWeakPtr()))); |
return; |
} |
- StartURLRequest(std::move(new_request)); |
+ StartURLRequest(mojom::URLLoaderFactoryPtrInfo(), std::move(new_request)); |
} |
NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} |
void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( |
mojom::URLLoaderFactoryPtr url_loader_factory) { |
- g_url_loader_factory.Get() = std::move(url_loader_factory); |
+ g_direct_network_url_loader_factory.Get() = std::move(url_loader_factory); |
} |
void NavigationURLLoaderNetworkService::FollowRedirect() { |
@@ -193,28 +259,33 @@ void NavigationURLLoaderNetworkService::OnComplete( |
} |
void NavigationURLLoaderNetworkService::StartURLRequest( |
+ mojom::URLLoaderFactoryPtrInfo url_loader_factory_info, |
std::unique_ptr<ResourceRequest> request) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ // If a URLLoaderFactory was provided, then we use that one, otherwise |
+ // fall back to connecting directly to the network service. |
+ if (url_loader_factory_info.is_valid()) { |
+ url_loader_factory_.Bind(std::move(url_loader_factory_info)); |
+ } else { |
+ if (!g_direct_network_url_loader_factory.Get()) { |
+ ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( |
+ mojom::kNetworkServiceName, |
+ &g_direct_network_url_loader_factory.Get()); |
+ } |
+ url_loader_factory_ = std::move(g_direct_network_url_loader_factory.Get()); |
+ } |
+ |
+ // Bind the URLClient implementation to this object to pass to the URLLoader. |
mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; |
binding_.Bind(&url_loader_client_ptr_to_pass); |
- GetURLLoaderFactory().CreateLoaderAndStart( |
+ // Use the URLLoaderFactory to create a URLLoader that uses |binding_| as the |
+ // URLLoaderClient. |
+ url_loader_factory_->CreateLoaderAndStart( |
mojo::MakeRequest(&url_loader_associated_ptr_), 0 /* routing_id? */, |
0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo, *request, |
std::move(url_loader_client_ptr_to_pass)); |
} |
-mojom::URLLoaderFactory& |
-NavigationURLLoaderNetworkService::GetURLLoaderFactory() { |
- // TODO(yzshen): We will need the ability to customize the factory per frame |
- // e.g., for appcache or service worker. |
- if (!g_url_loader_factory.Get()) { |
- ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( |
- mojom::kNetworkServiceName, &g_url_loader_factory.Get()); |
- } |
- |
- return *g_url_loader_factory.Get(); |
-} |
- |
} // namespace content |