| 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/appcache/appcache_navigation_handle.h" |
| 13 #include "content/browser/appcache/appcache_navigation_handle_core.h" |
| 14 #include "content/browser/appcache/appcache_request_handler.h" |
| 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 15 #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| 13 #include "content/browser/frame_host/frame_tree_node.h" | 16 #include "content/browser/frame_host/frame_tree_node.h" |
| 14 #include "content/browser/frame_host/navigation_request_info.h" | 17 #include "content/browser/frame_host/navigation_request_info.h" |
| 15 #include "content/browser/loader/navigation_resource_handler.h" | 18 #include "content/browser/loader/navigation_resource_handler.h" |
| 16 #include "content/browser/loader/navigation_resource_throttle.h" | 19 #include "content/browser/loader/navigation_resource_throttle.h" |
| 17 #include "content/browser/loader/navigation_url_loader_delegate.h" | 20 #include "content/browser/loader/navigation_url_loader_delegate.h" |
| 18 #include "content/browser/webui/url_data_manager_backend.h" | 21 #include "content/browser/webui/url_data_manager_backend.h" |
| 19 #include "content/browser/webui/web_ui_url_loader_factory.h" | 22 #include "content/browser/webui/web_ui_url_loader_factory.h" |
| 20 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/browser/global_request_id.h" | 24 #include "content/public/browser/global_request_id.h" |
| 22 #include "content/public/browser/navigation_data.h" | 25 #include "content/public/browser/navigation_data.h" |
| 23 #include "content/public/browser/navigation_ui_data.h" | 26 #include "content/public/browser/navigation_ui_data.h" |
| 24 #include "content/public/browser/ssl_status.h" | 27 #include "content/public/browser/ssl_status.h" |
| 25 #include "content/public/browser/stream_handle.h" | 28 #include "content/public/browser/stream_handle.h" |
| 26 #include "content/public/common/referrer.h" | 29 #include "content/public/common/referrer.h" |
| 27 #include "content/public/common/service_manager_connection.h" | 30 #include "content/public/common/service_manager_connection.h" |
| 28 #include "content/public/common/service_names.mojom.h" | 31 #include "content/public/common/service_names.mojom.h" |
| 29 #include "content/public/common/url_constants.h" | 32 #include "content/public/common/url_constants.h" |
| 30 #include "net/base/load_flags.h" | 33 #include "net/base/load_flags.h" |
| 31 #include "net/url_request/url_request_context.h" | 34 #include "net/url_request/url_request_context.h" |
| 32 #include "services/service_manager/public/cpp/connector.h" | 35 #include "services/service_manager/public/cpp/connector.h" |
| 33 | 36 |
| 34 namespace content { | 37 namespace content { |
| 35 | 38 |
| 36 namespace { | 39 namespace { |
| 37 | 40 |
| 38 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky | 41 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky |
| 39 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; | 42 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; |
| 40 | 43 |
| 41 // This function is called on the IO thread for POST/PUT requests for | 44 using CompleteNavigationStartCallback = |
| 42 // attaching blob information to the request body. | 45 base::Callback<void(mojom::URLLoaderFactoryPtrInfo, |
| 43 void HandleRequestsWithBody( | 46 std::unique_ptr<ResourceRequest>)>; |
| 44 std::unique_ptr<ResourceRequest> request, | 47 |
| 48 void PrepareNavigationOnIOThread( |
| 49 std::unique_ptr<ResourceRequest> resource_request, |
| 45 ResourceContext* resource_context, | 50 ResourceContext* resource_context, |
| 46 base::WeakPtr<NavigationURLLoaderNetworkService> url_loader) { | 51 ResourceType resource_type, |
| 47 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 52 AppCacheNavigationHandleCore* appcache_handle_core, |
| 48 DCHECK(request->request_body.get()); | 53 CompleteNavigationStartCallback complete_request) { |
| 54 if (resource_request->request_body.get()) { |
| 55 AttachRequestBodyBlobDataHandles(resource_request->request_body.get(), |
| 56 resource_context); |
| 57 } |
| 49 | 58 |
| 50 AttachRequestBodyBlobDataHandles(request->request_body.get(), | 59 mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; |
| 51 resource_context); | 60 |
| 61 if (appcache_handle_core) { |
| 62 AppCacheRequestHandler::InitializeForNavigationNetworkService( |
| 63 std::move(resource_request), resource_context, appcache_handle_core, |
| 64 resource_type, complete_request); |
| 65 return; |
| 66 } |
| 67 |
| 52 BrowserThread::PostTask( | 68 BrowserThread::PostTask( |
| 53 BrowserThread::UI, FROM_HERE, | 69 BrowserThread::UI, FROM_HERE, |
| 54 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, | 70 base::Bind(complete_request, |
| 55 url_loader, base::Passed(&request))); | 71 base::Passed(std::move(url_loader_factory_ptr_info)), |
| 72 base::Passed(std::move(resource_request)))); |
| 56 } | 73 } |
| 57 | 74 |
| 58 } // namespace | 75 } // namespace |
| 59 | 76 |
| 60 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( | 77 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| 61 ResourceContext* resource_context, | 78 ResourceContext* resource_context, |
| 62 StoragePartition* storage_partition, | 79 StoragePartition* storage_partition, |
| 63 std::unique_ptr<NavigationRequestInfo> request_info, | 80 std::unique_ptr<NavigationRequestInfo> request_info, |
| 64 std::unique_ptr<NavigationUIData> navigation_ui_data, | 81 std::unique_ptr<NavigationUIData> navigation_ui_data, |
| 65 ServiceWorkerNavigationHandle* service_worker_handle, | 82 ServiceWorkerNavigationHandle* service_worker_handle, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 if (request_info_->is_main_frame) | 115 if (request_info_->is_main_frame) |
| 99 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; | 116 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; |
| 100 | 117 |
| 101 // Sync loads should have maximum priority and should be the only | 118 // Sync loads should have maximum priority and should be the only |
| 102 // requests that have the ignore limits flag set. | 119 // requests that have the ignore limits flag set. |
| 103 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); | 120 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); |
| 104 | 121 |
| 105 new_request->load_flags = load_flags; | 122 new_request->load_flags = load_flags; |
| 106 | 123 |
| 107 new_request->request_body = request_info_->common_params.post_data.get(); | 124 new_request->request_body = request_info_->common_params.post_data.get(); |
| 108 if (new_request->request_body.get()) { | 125 |
| 109 // The request body may need blob handles to be added to it. This | 126 // AppCache or post data needs some handling on the IO thread. |
| 110 // functionality has to be invoked on the IO thread. | 127 // The request body may need blob handles to be added to it. This |
| 128 // functionality has to be invoked on the IO thread. |
| 129 if (/*appcache_handle || */ new_request->request_body.get()) { |
| 130 ResourceType resource_type = request_info_->is_main_frame |
| 131 ? RESOURCE_TYPE_MAIN_FRAME |
| 132 : RESOURCE_TYPE_SUB_FRAME; |
| 111 BrowserThread::PostTask( | 133 BrowserThread::PostTask( |
| 112 BrowserThread::IO, FROM_HERE, | 134 BrowserThread::IO, FROM_HERE, |
| 113 base::Bind(&HandleRequestsWithBody, | 135 base::Bind( |
| 114 base::Passed(&new_request), | 136 &PrepareNavigationOnIOThread, base::Passed(std::move(new_request)), |
| 115 resource_context, | 137 resource_context, resource_type, appcache_handle->core(), |
| 116 weak_factory_.GetWeakPtr())); | 138 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, |
| 139 weak_factory_.GetWeakPtr()))); |
| 117 return; | 140 return; |
| 118 } | 141 } |
| 119 | 142 StartURLRequest(mojom::URLLoaderFactoryPtrInfo(), std::move(new_request)); |
| 120 StartURLRequest(std::move(new_request)); | |
| 121 } | 143 } |
| 122 | 144 |
| 123 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} | 145 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} |
| 124 | 146 |
| 125 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( | 147 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( |
| 126 mojom::URLLoaderFactoryPtr url_loader_factory) { | 148 mojom::URLLoaderFactoryPtr url_loader_factory) { |
| 127 g_url_loader_factory.Get() = std::move(url_loader_factory); | 149 g_url_loader_factory.Get() = std::move(url_loader_factory); |
| 128 } | 150 } |
| 129 | 151 |
| 130 void NavigationURLLoaderNetworkService::FollowRedirect() { | 152 void NavigationURLLoaderNetworkService::FollowRedirect() { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", | 215 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", |
| 194 this, "&NavigationURLLoaderNetworkService", this, | 216 this, "&NavigationURLLoaderNetworkService", this, |
| 195 "success", false); | 217 "success", false); |
| 196 | 218 |
| 197 delegate_->OnRequestFailed(completion_status.exists_in_cache, | 219 delegate_->OnRequestFailed(completion_status.exists_in_cache, |
| 198 completion_status.error_code); | 220 completion_status.error_code); |
| 199 } | 221 } |
| 200 } | 222 } |
| 201 | 223 |
| 202 void NavigationURLLoaderNetworkService::StartURLRequest( | 224 void NavigationURLLoaderNetworkService::StartURLRequest( |
| 225 mojom::URLLoaderFactoryPtrInfo url_loader_factory_info, |
| 203 std::unique_ptr<ResourceRequest> request) { | 226 std::unique_ptr<ResourceRequest> request) { |
| 204 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 227 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 205 | 228 |
| 229 // Bind the URLClient implementation to this object to pass to the URLLoader. |
| 230 if (binding_.is_bound()) |
| 231 binding_.Unbind(); |
| 232 |
| 206 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; | 233 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; |
| 207 binding_.Bind(&url_loader_client_ptr_to_pass); | 234 binding_.Bind(&url_loader_client_ptr_to_pass); |
| 208 | 235 |
| 209 mojom::URLLoaderFactory* factory = nullptr; | 236 mojom::URLLoaderFactory* factory = nullptr; |
| 210 // This |factory_ptr| will be destroyed when it goes out of scope. Because | 237 // This |factory_ptr| will be destroyed when it goes out of scope. Because |
| 211 // |url_loader_associated_ptr_| is associated with it, it will be disconnected | 238 // |url_loader_associated_ptr_| is associated with it, it will be disconnected |
| 212 // as well. That means NavigationURLLoaderNetworkService::FollowRedirect() | 239 // as well. That means NavigationURLLoaderNetworkService::FollowRedirect() |
| 213 // won't work as expected, the |url_loader_associated_ptr_| will silently drop | 240 // won't work as expected, the |url_loader_associated_ptr_| will silently drop |
| 214 // calls. | 241 // calls. |
| 215 // This is fine for now since the only user of this is WebUI which doesn't | 242 // This is fine for now since the only user of this is WebUI which doesn't |
| 216 // need this, but we'll have to fix this when other consumers come up. | 243 // need this, but we'll have to fix this when other consumers come up. |
| 217 mojom::URLLoaderFactoryPtr factory_ptr; | 244 mojom::URLLoaderFactoryPtr factory_ptr; |
| 218 const auto& schemes = URLDataManagerBackend::GetWebUISchemes(); | 245 const auto& schemes = URLDataManagerBackend::GetWebUISchemes(); |
| 219 if (std::find(schemes.begin(), schemes.end(), request->url.scheme()) != | 246 if (std::find(schemes.begin(), schemes.end(), request->url.scheme()) != |
| 220 schemes.end()) { | 247 schemes.end()) { |
| 221 FrameTreeNode* frame_tree_node = | 248 FrameTreeNode* frame_tree_node = |
| 222 FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); | 249 FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); |
| 223 factory_ptr = GetWebUIURLLoader(frame_tree_node); | 250 factory_ptr = GetWebUIURLLoader(frame_tree_node); |
| 224 factory = factory_ptr.get(); | 251 factory = factory_ptr.get(); |
| 225 } | 252 } |
| 226 | 253 |
| 227 if (!factory) | 254 if (!factory) { |
| 228 factory = GetURLLoaderFactory(); | 255 // If a URLLoaderFactory was provided, then we use that one, otherwise |
| 256 // fall back to connecting directly to the network service. |
| 257 if (url_loader_factory_info.is_valid()) { |
| 258 url_loader_factory_.Bind(std::move(url_loader_factory_info)); |
| 259 factory = url_loader_factory_.get(); |
| 260 } else { |
| 261 factory = GetURLLoaderFactory(); |
| 262 } |
| 263 } |
| 229 | 264 |
| 230 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_associated_ptr_), | 265 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_associated_ptr_), |
| 231 0 /* routing_id? */, 0 /* request_id? */, | 266 0 /* routing_id? */, 0 /* request_id? */, |
| 232 mojom::kURLLoadOptionSendSSLInfo, *request, | 267 mojom::kURLLoadOptionSendSSLInfo, *request, |
| 233 std::move(url_loader_client_ptr_to_pass)); | 268 std::move(url_loader_client_ptr_to_pass)); |
| 234 } | 269 } |
| 235 | 270 |
| 236 mojom::URLLoaderFactory* | 271 mojom::URLLoaderFactory* |
| 237 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { | 272 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { |
| 238 // TODO(yzshen): We will need the ability to customize the factory per frame | 273 // TODO(yzshen): We will need the ability to customize the factory per frame |
| 239 // e.g., for appcache or service worker. | 274 // e.g., for appcache or service worker. |
| 240 if (!g_url_loader_factory.Get()) { | 275 if (!g_url_loader_factory.Get()) { |
| 241 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( | 276 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( |
| 242 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); | 277 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); |
| 243 } | 278 } |
| 244 | 279 |
| 245 return g_url_loader_factory.Get().get(); | 280 return g_url_loader_factory.Get().get(); |
| 246 } | 281 } |
| 247 | 282 |
| 248 } // namespace content | 283 } // namespace content |
| OLD | NEW |