OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/loader/navigation_url_loader_network_service.h" | 5 #include "content/browser/loader/navigation_url_loader_network_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| 13 #include "content/browser/frame_host/frame_tree_node.h" |
13 #include "content/browser/frame_host/navigation_request_info.h" | 14 #include "content/browser/frame_host/navigation_request_info.h" |
14 #include "content/browser/loader/navigation_resource_handler.h" | 15 #include "content/browser/loader/navigation_resource_handler.h" |
15 #include "content/browser/loader/navigation_resource_throttle.h" | 16 #include "content/browser/loader/navigation_resource_throttle.h" |
16 #include "content/browser/loader/navigation_url_loader_delegate.h" | 17 #include "content/browser/loader/navigation_url_loader_delegate.h" |
| 18 #include "content/browser/resource_context_impl.h" |
| 19 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 20 #include "content/browser/service_worker/service_worker_navigation_handle.h" |
| 21 #include "content/browser/service_worker/service_worker_navigation_handle_core.h
" |
| 22 #include "content/browser/service_worker/service_worker_request_handler.h" |
| 23 #include "content/browser/web_contents/web_contents_impl.h" |
17 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/global_request_id.h" | 25 #include "content/public/browser/global_request_id.h" |
19 #include "content/public/browser/navigation_data.h" | 26 #include "content/public/browser/navigation_data.h" |
20 #include "content/public/browser/navigation_ui_data.h" | 27 #include "content/public/browser/navigation_ui_data.h" |
21 #include "content/public/browser/ssl_status.h" | 28 #include "content/public/browser/ssl_status.h" |
22 #include "content/public/browser/stream_handle.h" | 29 #include "content/public/browser/stream_handle.h" |
23 #include "content/public/common/referrer.h" | 30 #include "content/public/common/referrer.h" |
24 #include "content/public/common/service_manager_connection.h" | 31 #include "content/public/common/service_manager_connection.h" |
25 #include "content/public/common/service_names.mojom.h" | 32 #include "content/public/common/service_names.mojom.h" |
26 #include "net/base/load_flags.h" | 33 #include "net/base/load_flags.h" |
27 #include "net/url_request/url_request_context.h" | 34 #include "net/url_request/url_request_context.h" |
28 #include "services/service_manager/public/cpp/connector.h" | 35 #include "services/service_manager/public/cpp/connector.h" |
29 | 36 |
30 namespace content { | 37 namespace content { |
31 | 38 |
32 namespace { | 39 namespace { |
33 | 40 |
34 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky | 41 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky |
35 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; | 42 g_direct_network_url_loader_factory = LAZY_INSTANCE_INITIALIZER; |
36 | 43 |
37 // This function is called on the IO thread for POST/PUT requests for | 44 using CompleteNavigationStart = |
38 // attaching blob information to the request body. | 45 base::Callback<void(mojom::URLLoaderFactoryPtrInfo, |
39 void HandleRequestsWithBody( | 46 std::unique_ptr<ResourceRequest>)>; |
40 std::unique_ptr<ResourceRequest> request, | 47 |
| 48 void NavigationStartupWorkOnIO( |
| 49 std::unique_ptr<ResourceRequest> resource_request, |
41 ResourceContext* resource_context, | 50 ResourceContext* resource_context, |
42 base::WeakPtr<NavigationURLLoaderNetworkService> url_loader) { | 51 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
| 52 bool skip_service_worker, |
| 53 ResourceType resource_type, |
| 54 RequestContextType request_context_type, |
| 55 RequestContextFrameType frame_type, |
| 56 bool is_parent_frame_secure, |
| 57 scoped_refptr<ResourceRequestBodyImpl> body, |
| 58 const base::Callback<WebContents*(void)>& web_contents_getter, |
| 59 CompleteNavigationStart complete_request) { |
43 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 60 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
44 DCHECK(request->request_body.get()); | 61 DCHECK(service_worker_navigation_handle_core || |
| 62 resource_request->request_body.get()); |
45 | 63 |
46 AttachRequestBodyBlobDataHandles(request->request_body.get(), | 64 mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; |
47 resource_context); | 65 if (service_worker_navigation_handle_core) { |
| 66 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext( |
| 67 GetChromeBlobStorageContextForResourceContext(resource_context)); |
| 68 url_loader_factory_ptr_info = |
| 69 ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( |
| 70 *resource_request, resource_context, |
| 71 service_worker_navigation_handle_core, blob_storage_context, |
| 72 skip_service_worker, resource_type, request_context_type, |
| 73 frame_type, is_parent_frame_secure, body, web_contents_getter); |
| 74 } |
| 75 |
| 76 if (resource_request->request_body) { |
| 77 AttachRequestBodyBlobDataHandles(resource_request->request_body.get(), |
| 78 resource_context); |
| 79 } |
| 80 |
48 BrowserThread::PostTask( | 81 BrowserThread::PostTask( |
49 BrowserThread::UI, FROM_HERE, | 82 BrowserThread::UI, FROM_HERE, |
50 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, | 83 base::Bind(complete_request, |
51 url_loader, base::Passed(&request))); | 84 base::Passed(std::move(url_loader_factory_ptr_info)), |
| 85 base::Passed(std::move(resource_request)))); |
| 86 } |
| 87 |
| 88 WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) { |
| 89 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 90 FrameTreeNode* frame_tree_node = |
| 91 FrameTreeNode::GloballyFindByID(frame_tree_node_id); |
| 92 if (!frame_tree_node) |
| 93 return nullptr; |
| 94 |
| 95 return WebContentsImpl::FromFrameTreeNode(frame_tree_node); |
52 } | 96 } |
53 | 97 |
54 } // namespace | 98 } // namespace |
55 | 99 |
56 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( | 100 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
57 ResourceContext* resource_context, | 101 ResourceContext* resource_context, |
58 StoragePartition* storage_partition, | 102 StoragePartition* storage_partition, |
59 std::unique_ptr<NavigationRequestInfo> request_info, | 103 std::unique_ptr<NavigationRequestInfo> request_info, |
60 std::unique_ptr<NavigationUIData> navigation_ui_data, | 104 std::unique_ptr<NavigationUIData> navigation_ui_data, |
61 ServiceWorkerNavigationHandle* service_worker_handle, | 105 ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
62 AppCacheNavigationHandle* appcache_handle, | 106 AppCacheNavigationHandle* appcache_handle, |
63 NavigationURLLoaderDelegate* delegate) | 107 NavigationURLLoaderDelegate* delegate) |
64 : delegate_(delegate), binding_(this), weak_factory_(this) { | 108 : delegate_(delegate), binding_(this), weak_factory_(this) { |
65 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 109 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
66 | 110 |
67 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( | 111 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( |
68 "navigation", "Navigation timeToResponseStarted", this, | 112 "navigation", "Navigation timeToResponseStarted", this, |
69 request_info->common_params.navigation_start, "FrameTreeNode id", | 113 request_info->common_params.navigation_start, "FrameTreeNode id", |
70 request_info->frame_tree_node_id); | 114 request_info->frame_tree_node_id); |
71 | 115 |
(...skipping 19 matching lines...) Expand all Loading... |
91 if (request_info->is_main_frame) | 135 if (request_info->is_main_frame) |
92 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; | 136 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; |
93 | 137 |
94 // Sync loads should have maximum priority and should be the only | 138 // Sync loads should have maximum priority and should be the only |
95 // requests that have the ignore limits flag set. | 139 // requests that have the ignore limits flag set. |
96 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); | 140 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); |
97 | 141 |
98 new_request->load_flags = load_flags; | 142 new_request->load_flags = load_flags; |
99 | 143 |
100 new_request->request_body = request_info->common_params.post_data.get(); | 144 new_request->request_body = request_info->common_params.post_data.get(); |
101 if (new_request->request_body.get()) { | 145 |
102 // The request body may need blob handles to be added to it. This | 146 ResourceType resource_type = request_info->is_main_frame |
103 // functionality has to be invoked on the IO thread. | 147 ? RESOURCE_TYPE_MAIN_FRAME |
| 148 : RESOURCE_TYPE_SUB_FRAME; |
| 149 RequestContextFrameType frame_type = |
| 150 request_info->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL |
| 151 : REQUEST_CONTEXT_FRAME_TYPE_NESTED; |
| 152 |
| 153 // Determine where the request will be serviced. If there's work that needs to |
| 154 // be done on the IO thread due to Service Worker or POST body, then post to |
| 155 // the IO thread to have it do that work, and then continue on to |
| 156 // StartURLRequest. Otherwise, handle the request directly. |
| 157 const bool need_to_work_on_io = |
| 158 service_worker_navigation_handle || new_request->request_body; |
| 159 if (need_to_work_on_io) { |
104 BrowserThread::PostTask( | 160 BrowserThread::PostTask( |
105 BrowserThread::IO, FROM_HERE, | 161 BrowserThread::IO, FROM_HERE, |
106 base::Bind(&HandleRequestsWithBody, | 162 base::Bind( |
107 base::Passed(&new_request), | 163 &NavigationStartupWorkOnIO, base::Passed(std::move(new_request)), |
108 resource_context, | 164 resource_context, |
109 weak_factory_.GetWeakPtr())); | 165 service_worker_navigation_handle |
| 166 ? service_worker_navigation_handle->core() |
| 167 : nullptr, |
| 168 request_info->begin_params.skip_service_worker, resource_type, |
| 169 request_info->begin_params.request_context_type, frame_type, |
| 170 request_info->are_ancestors_secure, |
| 171 request_info->common_params.post_data, |
| 172 base::Bind(&GetWebContentsFromFrameTreeNodeID, |
| 173 request_info->frame_tree_node_id), |
| 174 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, |
| 175 weak_factory_.GetWeakPtr()))); |
110 return; | 176 return; |
111 } | 177 } |
112 | 178 |
113 StartURLRequest(std::move(new_request)); | 179 StartURLRequest(mojom::URLLoaderFactoryPtrInfo(), std::move(new_request)); |
114 } | 180 } |
115 | 181 |
116 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} | 182 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} |
117 | 183 |
118 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( | 184 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( |
119 mojom::URLLoaderFactoryPtr url_loader_factory) { | 185 mojom::URLLoaderFactoryPtr url_loader_factory) { |
120 g_url_loader_factory.Get() = std::move(url_loader_factory); | 186 g_direct_network_url_loader_factory.Get() = std::move(url_loader_factory); |
121 } | 187 } |
122 | 188 |
123 void NavigationURLLoaderNetworkService::FollowRedirect() { | 189 void NavigationURLLoaderNetworkService::FollowRedirect() { |
124 url_loader_associated_ptr_->FollowRedirect(); | 190 url_loader_associated_ptr_->FollowRedirect(); |
125 } | 191 } |
126 | 192 |
127 void NavigationURLLoaderNetworkService::ProceedWithResponse() {} | 193 void NavigationURLLoaderNetworkService::ProceedWithResponse() {} |
128 | 194 |
129 void NavigationURLLoaderNetworkService::OnReceiveResponse( | 195 void NavigationURLLoaderNetworkService::OnReceiveResponse( |
130 const ResourceResponseHead& head, | 196 const ResourceResponseHead& head, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", | 252 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", |
187 this, "&NavigationURLLoaderNetworkService", this, | 253 this, "&NavigationURLLoaderNetworkService", this, |
188 "success", false); | 254 "success", false); |
189 | 255 |
190 delegate_->OnRequestFailed(completion_status.exists_in_cache, | 256 delegate_->OnRequestFailed(completion_status.exists_in_cache, |
191 completion_status.error_code); | 257 completion_status.error_code); |
192 } | 258 } |
193 } | 259 } |
194 | 260 |
195 void NavigationURLLoaderNetworkService::StartURLRequest( | 261 void NavigationURLLoaderNetworkService::StartURLRequest( |
| 262 mojom::URLLoaderFactoryPtrInfo url_loader_factory_info, |
196 std::unique_ptr<ResourceRequest> request) { | 263 std::unique_ptr<ResourceRequest> request) { |
197 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 264 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
198 | 265 |
| 266 // If a URLLoaderFactory was provided, then we use that one, otherwise |
| 267 // fall back to connecting directly to the network service. |
| 268 if (url_loader_factory_info.is_valid()) { |
| 269 url_loader_factory_.Bind(std::move(url_loader_factory_info)); |
| 270 } else { |
| 271 if (!g_direct_network_url_loader_factory.Get()) { |
| 272 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( |
| 273 mojom::kNetworkServiceName, |
| 274 &g_direct_network_url_loader_factory.Get()); |
| 275 } |
| 276 url_loader_factory_ = std::move(g_direct_network_url_loader_factory.Get()); |
| 277 } |
| 278 |
| 279 // Bind the URLClient implementation to this object to pass to the URLLoader. |
199 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; | 280 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; |
200 binding_.Bind(&url_loader_client_ptr_to_pass); | 281 binding_.Bind(&url_loader_client_ptr_to_pass); |
201 | 282 |
202 GetURLLoaderFactory().CreateLoaderAndStart( | 283 // Use the URLLoaderFactory to create a URLLoader that uses |binding_| as the |
| 284 // URLLoaderClient. |
| 285 url_loader_factory_->CreateLoaderAndStart( |
203 mojo::MakeRequest(&url_loader_associated_ptr_), 0 /* routing_id? */, | 286 mojo::MakeRequest(&url_loader_associated_ptr_), 0 /* routing_id? */, |
204 0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo, *request, | 287 0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo, *request, |
205 std::move(url_loader_client_ptr_to_pass)); | 288 std::move(url_loader_client_ptr_to_pass)); |
206 } | 289 } |
207 | 290 |
208 mojom::URLLoaderFactory& | |
209 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { | |
210 // TODO(yzshen): We will need the ability to customize the factory per frame | |
211 // e.g., for appcache or service worker. | |
212 if (!g_url_loader_factory.Get()) { | |
213 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( | |
214 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); | |
215 } | |
216 | |
217 return *g_url_loader_factory.Get(); | |
218 } | |
219 | |
220 } // namespace content | 291 } // namespace content |
OLD | NEW |