Chromium Code Reviews| 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/frame_tree_node.h" |
| 14 #include "content/browser/frame_host/navigation_request_info.h" | 14 #include "content/browser/frame_host/navigation_request_info.h" |
| 15 #include "content/browser/loader/navigation_resource_handler.h" | 15 #include "content/browser/loader/navigation_resource_handler.h" |
| 16 #include "content/browser/loader/navigation_resource_throttle.h" | 16 #include "content/browser/loader/navigation_resource_throttle.h" |
| 17 #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" | |
| 18 #include "content/browser/webui/web_ui_url_loader_factory.h" | 24 #include "content/browser/webui/web_ui_url_loader_factory.h" |
| 19 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/global_request_id.h" | 26 #include "content/public/browser/global_request_id.h" |
| 21 #include "content/public/browser/navigation_data.h" | 27 #include "content/public/browser/navigation_data.h" |
| 22 #include "content/public/browser/navigation_ui_data.h" | 28 #include "content/public/browser/navigation_ui_data.h" |
| 23 #include "content/public/browser/ssl_status.h" | 29 #include "content/public/browser/ssl_status.h" |
| 24 #include "content/public/browser/stream_handle.h" | 30 #include "content/public/browser/stream_handle.h" |
| 25 #include "content/public/common/referrer.h" | 31 #include "content/public/common/referrer.h" |
| 26 #include "content/public/common/service_manager_connection.h" | 32 #include "content/public/common/service_manager_connection.h" |
| 27 #include "content/public/common/service_names.mojom.h" | 33 #include "content/public/common/service_names.mojom.h" |
| 28 #include "content/public/common/url_constants.h" | 34 #include "content/public/common/url_constants.h" |
| 29 #include "net/base/load_flags.h" | 35 #include "net/base/load_flags.h" |
| 30 #include "net/url_request/url_request_context.h" | 36 #include "net/url_request/url_request_context.h" |
| 31 #include "services/service_manager/public/cpp/connector.h" | 37 #include "services/service_manager/public/cpp/connector.h" |
| 32 | 38 |
| 33 namespace content { | 39 namespace content { |
| 34 | 40 |
| 35 namespace { | 41 namespace { |
| 36 | 42 |
| 37 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky | 43 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky |
| 38 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; | 44 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; |
| 39 | 45 |
| 40 // This function is called on the IO thread for POST/PUT requests for | 46 using CompleteNavigationStart = |
|
kinuko
2017/05/09 14:45:25
nit: CompleteNavigationStartCallback
(preferring
scottmg
2017/05/09 22:14:10
Done.
| |
| 41 // attaching blob information to the request body. | 47 base::Callback<void(mojom::URLLoaderFactoryPtrInfo, |
| 42 void HandleRequestsWithBody( | 48 std::unique_ptr<ResourceRequest>)>; |
| 43 std::unique_ptr<ResourceRequest> request, | 49 |
| 50 void NavigationStartupWorkOnIO( | |
|
kinuko
2017/05/09 14:45:25
nit: maybe... PrepareNavigationStartOnIOThread
scottmg
2017/05/09 22:14:10
Done.
| |
| 51 std::unique_ptr<ResourceRequest> resource_request, | |
| 44 ResourceContext* resource_context, | 52 ResourceContext* resource_context, |
| 45 base::WeakPtr<NavigationURLLoaderNetworkService> url_loader) { | 53 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
| 54 bool skip_service_worker, | |
| 55 ResourceType resource_type, | |
| 56 RequestContextType request_context_type, | |
| 57 RequestContextFrameType frame_type, | |
| 58 bool is_parent_frame_secure, | |
| 59 scoped_refptr<ResourceRequestBodyImpl> body, | |
| 60 const base::Callback<WebContents*(void)>& web_contents_getter, | |
| 61 CompleteNavigationStart complete_request) { | |
| 46 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 62 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 47 DCHECK(request->request_body.get()); | 63 DCHECK(service_worker_navigation_handle_core || |
| 64 resource_request->request_body.get()); | |
| 48 | 65 |
| 49 AttachRequestBodyBlobDataHandles(request->request_body.get(), | 66 mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; |
| 50 resource_context); | 67 if (service_worker_navigation_handle_core) { |
| 68 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext( | |
| 69 GetChromeBlobStorageContextForResourceContext(resource_context)); | |
| 70 url_loader_factory_ptr_info = | |
| 71 ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( | |
| 72 *resource_request, resource_context, | |
| 73 service_worker_navigation_handle_core, blob_storage_context, | |
| 74 skip_service_worker, resource_type, request_context_type, | |
| 75 frame_type, is_parent_frame_secure, body, web_contents_getter, | |
| 76 // This is a fallback callback if the service worker handler decides | |
| 77 // later that the request should fallback to the network. | |
| 78 base::Bind( | |
| 79 complete_request, | |
| 80 base::Passed(std::move(mojom::URLLoaderFactoryPtrInfo())))); | |
|
kinuko
2017/05/09 14:45:25
I think it'd be probably nicer to have some code s
scottmg
2017/05/09 22:14:10
Yes, we'll need something like that in the full ap
| |
| 81 } | |
| 82 | |
| 83 if (resource_request->request_body) { | |
| 84 AttachRequestBodyBlobDataHandles(resource_request->request_body.get(), | |
| 85 resource_context); | |
| 86 } | |
| 87 | |
| 51 BrowserThread::PostTask( | 88 BrowserThread::PostTask( |
| 52 BrowserThread::UI, FROM_HERE, | 89 BrowserThread::UI, FROM_HERE, |
| 53 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, | 90 base::Bind(complete_request, |
| 54 url_loader, base::Passed(&request))); | 91 base::Passed(std::move(url_loader_factory_ptr_info)), |
| 92 base::Passed(std::move(resource_request)))); | |
| 93 } | |
| 94 | |
| 95 WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) { | |
| 96 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 97 FrameTreeNode* frame_tree_node = | |
| 98 FrameTreeNode::GloballyFindByID(frame_tree_node_id); | |
| 99 if (!frame_tree_node) | |
| 100 return nullptr; | |
| 101 | |
| 102 return WebContentsImpl::FromFrameTreeNode(frame_tree_node); | |
| 55 } | 103 } |
| 56 | 104 |
| 57 } // namespace | 105 } // namespace |
| 58 | 106 |
| 59 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( | 107 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| 60 ResourceContext* resource_context, | 108 ResourceContext* resource_context, |
| 61 StoragePartition* storage_partition, | 109 StoragePartition* storage_partition, |
| 62 std::unique_ptr<NavigationRequestInfo> request_info, | 110 std::unique_ptr<NavigationRequestInfo> request_info, |
| 63 std::unique_ptr<NavigationUIData> navigation_ui_data, | 111 std::unique_ptr<NavigationUIData> navigation_ui_data, |
| 64 ServiceWorkerNavigationHandle* service_worker_handle, | 112 ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
| 65 AppCacheNavigationHandle* appcache_handle, | 113 AppCacheNavigationHandle* appcache_handle, |
| 66 NavigationURLLoaderDelegate* delegate) | 114 NavigationURLLoaderDelegate* delegate) |
| 67 : delegate_(delegate), | 115 : delegate_(delegate), |
| 68 binding_(this), | 116 binding_(this), |
| 69 request_info_(std::move(request_info)), | 117 request_info_(std::move(request_info)), |
| 70 weak_factory_(this) { | 118 weak_factory_(this) { |
| 71 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 119 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 72 | 120 |
| 73 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( | 121 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( |
| 74 "navigation", "Navigation timeToResponseStarted", this, | 122 "navigation", "Navigation timeToResponseStarted", this, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 97 if (request_info_->is_main_frame) | 145 if (request_info_->is_main_frame) |
| 98 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; | 146 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; |
| 99 | 147 |
| 100 // Sync loads should have maximum priority and should be the only | 148 // Sync loads should have maximum priority and should be the only |
| 101 // requests that have the ignore limits flag set. | 149 // requests that have the ignore limits flag set. |
| 102 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); | 150 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); |
| 103 | 151 |
| 104 new_request->load_flags = load_flags; | 152 new_request->load_flags = load_flags; |
| 105 | 153 |
| 106 new_request->request_body = request_info_->common_params.post_data.get(); | 154 new_request->request_body = request_info_->common_params.post_data.get(); |
| 107 if (new_request->request_body.get()) { | 155 |
| 108 // The request body may need blob handles to be added to it. This | 156 ResourceType resource_type = request_info_->is_main_frame |
| 109 // functionality has to be invoked on the IO thread. | 157 ? RESOURCE_TYPE_MAIN_FRAME |
| 158 : RESOURCE_TYPE_SUB_FRAME; | |
| 159 RequestContextFrameType frame_type = | |
| 160 request_info_->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL | |
| 161 : REQUEST_CONTEXT_FRAME_TYPE_NESTED; | |
| 162 | |
| 163 // Determine where the request will be serviced. If there's work that needs to | |
| 164 // be done on the IO thread due to Service Worker or POST body, then post to | |
| 165 // the IO thread to have it do that work, and then continue on to | |
| 166 // StartURLRequest. Otherwise, handle the request directly. | |
| 167 const bool need_to_work_on_io = | |
| 168 service_worker_navigation_handle || new_request->request_body; | |
| 169 if (need_to_work_on_io) { | |
| 110 BrowserThread::PostTask( | 170 BrowserThread::PostTask( |
| 111 BrowserThread::IO, FROM_HERE, | 171 BrowserThread::IO, FROM_HERE, |
| 112 base::Bind(&HandleRequestsWithBody, | 172 base::Bind( |
| 113 base::Passed(&new_request), | 173 &NavigationStartupWorkOnIO, base::Passed(std::move(new_request)), |
| 114 resource_context, | 174 resource_context, |
| 115 weak_factory_.GetWeakPtr())); | 175 service_worker_navigation_handle |
| 176 ? service_worker_navigation_handle->core() | |
| 177 : nullptr, | |
| 178 request_info_->begin_params.skip_service_worker, resource_type, | |
| 179 request_info_->begin_params.request_context_type, frame_type, | |
| 180 request_info_->are_ancestors_secure, | |
| 181 request_info_->common_params.post_data, | |
| 182 base::Bind(&GetWebContentsFromFrameTreeNodeID, | |
| 183 request_info_->frame_tree_node_id), | |
| 184 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, | |
| 185 weak_factory_.GetWeakPtr()))); | |
| 116 return; | 186 return; |
| 117 } | 187 } |
| 118 | 188 |
| 119 StartURLRequest(std::move(new_request)); | 189 StartURLRequest(mojom::URLLoaderFactoryPtrInfo(), std::move(new_request)); |
| 120 } | 190 } |
| 121 | 191 |
| 122 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} | 192 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} |
| 123 | 193 |
| 124 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( | 194 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( |
| 125 mojom::URLLoaderFactoryPtr url_loader_factory) { | 195 mojom::URLLoaderFactoryPtr url_loader_factory) { |
| 126 g_url_loader_factory.Get() = std::move(url_loader_factory); | 196 g_url_loader_factory.Get() = std::move(url_loader_factory); |
| 127 } | 197 } |
| 128 | 198 |
| 129 void NavigationURLLoaderNetworkService::FollowRedirect() { | 199 void NavigationURLLoaderNetworkService::FollowRedirect() { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", | 262 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", |
| 193 this, "&NavigationURLLoaderNetworkService", this, | 263 this, "&NavigationURLLoaderNetworkService", this, |
| 194 "success", false); | 264 "success", false); |
| 195 | 265 |
| 196 delegate_->OnRequestFailed(completion_status.exists_in_cache, | 266 delegate_->OnRequestFailed(completion_status.exists_in_cache, |
| 197 completion_status.error_code); | 267 completion_status.error_code); |
| 198 } | 268 } |
| 199 } | 269 } |
| 200 | 270 |
| 201 void NavigationURLLoaderNetworkService::StartURLRequest( | 271 void NavigationURLLoaderNetworkService::StartURLRequest( |
| 272 mojom::URLLoaderFactoryPtrInfo url_loader_factory_info, | |
| 202 std::unique_ptr<ResourceRequest> request) { | 273 std::unique_ptr<ResourceRequest> request) { |
| 203 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 274 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 204 | 275 |
| 276 // Bind the URLClient implementation to this object to pass to the URLLoader. | |
| 277 if (binding_.is_bound()) | |
| 278 binding_.Unbind(); | |
| 205 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; | 279 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; |
| 206 binding_.Bind(&url_loader_client_ptr_to_pass); | 280 binding_.Bind(&url_loader_client_ptr_to_pass); |
| 207 | 281 |
| 208 mojom::URLLoaderFactory* factory = nullptr; | 282 mojom::URLLoaderFactory* factory = nullptr; |
| 209 // This |factory_ptr| will be destroyed when it goes out of scope. Because | 283 // This |factory_ptr| will be destroyed when it goes out of scope. Because |
| 210 // |url_loader_associated_ptr_| is associated with it, it will be disconnected | 284 // |url_loader_associated_ptr_| is associated with it, it will be disconnected |
| 211 // as well. That means NavigationURLLoaderNetworkService::FollowRedirect() | 285 // as well. That means NavigationURLLoaderNetworkService::FollowRedirect() |
| 212 // won't work as expected, the |url_loader_associated_ptr_| will silently drop | 286 // won't work as expected, the |url_loader_associated_ptr_| will silently drop |
| 213 // calls. | 287 // calls. |
| 214 // This is fine for now since the only user of this is WebUI which doesn't | 288 // This is fine for now since the only user of this is WebUI which doesn't |
| 215 // need this, but we'll have to fix this when other consumers come up. | 289 // need this, but we'll have to fix this when other consumers come up. |
| 216 mojom::URLLoaderFactoryPtr factory_ptr; | 290 mojom::URLLoaderFactoryPtr factory_ptr; |
| 217 if (request->url.SchemeIs(kChromeUIScheme)) { | 291 if (request->url.SchemeIs(kChromeUIScheme)) { |
| 218 FrameTreeNode* frame_tree_node = | 292 FrameTreeNode* frame_tree_node = |
| 219 FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); | 293 FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); |
| 220 factory_ptr = GetWebUIURLLoader(frame_tree_node); | 294 factory_ptr = GetWebUIURLLoader(frame_tree_node); |
| 221 factory = factory_ptr.get(); | 295 factory = factory_ptr.get(); |
| 222 } | 296 } |
| 223 | 297 |
| 224 if (!factory) | 298 if (!factory) { |
| 225 factory = GetURLLoaderFactory(); | 299 // If a URLLoaderFactory was provided, then we use that one, otherwise |
| 300 // fall back to connecting directly to the network service. | |
| 301 if (url_loader_factory_info.is_valid()) { | |
| 302 url_loader_factory_.Bind(std::move(url_loader_factory_info)); | |
| 303 factory = url_loader_factory_.get(); | |
| 304 } else { | |
| 305 factory = GetURLLoaderFactory(); | |
| 306 } | |
| 307 } | |
| 226 | 308 |
| 227 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_associated_ptr_), | 309 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_associated_ptr_), |
| 228 0 /* routing_id? */, 0 /* request_id? */, | 310 0 /* routing_id? */, 0 /* request_id? */, |
| 229 mojom::kURLLoadOptionSendSSLInfo, *request, | 311 mojom::kURLLoadOptionSendSSLInfo, *request, |
| 230 std::move(url_loader_client_ptr_to_pass)); | 312 std::move(url_loader_client_ptr_to_pass)); |
| 231 } | 313 } |
| 232 | 314 |
| 233 mojom::URLLoaderFactory* | 315 mojom::URLLoaderFactory* |
| 234 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { | 316 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { |
| 235 // TODO(yzshen): We will need the ability to customize the factory per frame | 317 // TODO(yzshen): We will need the ability to customize the factory per frame |
| 236 // e.g., for appcache or service worker. | 318 // e.g., for appcache or service worker. |
| 237 if (!g_url_loader_factory.Get()) { | 319 if (!g_url_loader_factory.Get()) { |
| 238 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( | 320 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( |
| 239 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); | 321 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); |
| 240 } | 322 } |
| 241 | 323 |
| 242 return g_url_loader_factory.Get().get(); | 324 return g_url_loader_factory.Get().get(); |
| 243 } | 325 } |
| 244 | 326 |
| 245 } // namespace content | 327 } // namespace content |
| OLD | NEW |