| 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/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 : public mojom::URLLoaderClient { | 98 : public mojom::URLLoaderClient { |
| 99 public: | 99 public: |
| 100 URLLoaderRequestController( | 100 URLLoaderRequestController( |
| 101 std::unique_ptr<ResourceRequest> resource_request, | 101 std::unique_ptr<ResourceRequest> resource_request, |
| 102 ResourceContext* resource_context, | 102 ResourceContext* resource_context, |
| 103 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter, | 103 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter, |
| 104 const base::WeakPtr<NavigationURLLoaderNetworkService>& owner) | 104 const base::WeakPtr<NavigationURLLoaderNetworkService>& owner) |
| 105 : resource_request_(std::move(resource_request)), | 105 : resource_request_(std::move(resource_request)), |
| 106 resource_context_(resource_context), | 106 resource_context_(resource_context), |
| 107 default_url_loader_factory_getter_(default_url_loader_factory_getter), | 107 default_url_loader_factory_getter_(default_url_loader_factory_getter), |
| 108 owner_(owner) {} | 108 owner_(owner), |
| 109 response_loader_binding_(this) {} |
| 109 | 110 |
| 110 ~URLLoaderRequestController() override { | 111 ~URLLoaderRequestController() override { |
| 111 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 112 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 112 } | 113 } |
| 113 | 114 |
| 114 void Start( | 115 void Start( |
| 115 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, | 116 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
| 116 AppCacheNavigationHandleCore* appcache_handle_core, | 117 AppCacheNavigationHandleCore* appcache_handle_core, |
| 117 std::unique_ptr<NavigationRequestInfo> request_info, | 118 std::unique_ptr<NavigationRequestInfo> request_info, |
| 118 mojom::URLLoaderFactoryPtrInfo factory_for_webui, | 119 mojom::URLLoaderFactoryPtrInfo factory_for_webui, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 if (appcache_handler) | 171 if (appcache_handler) |
| 171 handlers_.push_back(std::move(appcache_handler)); | 172 handlers_.push_back(std::move(appcache_handler)); |
| 172 } | 173 } |
| 173 | 174 |
| 174 Restart(); | 175 Restart(); |
| 175 } | 176 } |
| 176 | 177 |
| 177 // This could be called multiple times. | 178 // This could be called multiple times. |
| 178 void Restart() { | 179 void Restart() { |
| 179 handler_index_ = 0; | 180 handler_index_ = 0; |
| 181 received_response_ = false; |
| 180 MaybeStartLoader(StartLoaderCallback()); | 182 MaybeStartLoader(StartLoaderCallback()); |
| 181 } | 183 } |
| 182 | 184 |
| 183 void MaybeStartLoader(StartLoaderCallback start_loader_callback) { | 185 void MaybeStartLoader(StartLoaderCallback start_loader_callback) { |
| 184 if (start_loader_callback) { | 186 if (start_loader_callback) { |
| 185 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( | 187 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( |
| 186 std::move(start_loader_callback), | 188 std::move(start_loader_callback), |
| 187 GetContentClient()->browser()->CreateURLLoaderThrottles( | 189 GetContentClient()->browser()->CreateURLLoaderThrottles( |
| 188 web_contents_getter_), | 190 web_contents_getter_), |
| 189 *resource_request_, this, kTrafficAnnotation); | 191 *resource_request_, this, kTrafficAnnotation); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 206 base::Unretained(this))); | 208 base::Unretained(this))); |
| 207 return; | 209 return; |
| 208 } | 210 } |
| 209 | 211 |
| 210 mojom::URLLoaderFactory* factory = nullptr; | 212 mojom::URLLoaderFactory* factory = nullptr; |
| 211 DCHECK_EQ(handlers_.size(), handler_index_); | 213 DCHECK_EQ(handlers_.size(), handler_index_); |
| 212 if (resource_request_->url.SchemeIs(url::kBlobScheme)) { | 214 if (resource_request_->url.SchemeIs(url::kBlobScheme)) { |
| 213 factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); | 215 factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); |
| 214 } else { | 216 } else { |
| 215 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); | 217 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); |
| 218 default_loader_used_ = true; |
| 216 } | 219 } |
| 217 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( | 220 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( |
| 218 factory, | 221 factory, |
| 219 GetContentClient()->browser()->CreateURLLoaderThrottles( | 222 GetContentClient()->browser()->CreateURLLoaderThrottles( |
| 220 web_contents_getter_), | 223 web_contents_getter_), |
| 221 0 /* routing_id? */, 0 /* request_id? */, | 224 0 /* routing_id? */, 0 /* request_id? */, |
| 222 mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType, | 225 mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType, |
| 223 *resource_request_, this, kTrafficAnnotation); | 226 *resource_request_, this, kTrafficAnnotation); |
| 224 } | 227 } |
| 225 | 228 |
| 226 void FollowRedirect() { | 229 void FollowRedirect() { |
| 227 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 230 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 228 DCHECK(url_loader_); | 231 DCHECK(url_loader_); |
| 229 | 232 |
| 233 DCHECK(!response_url_loader_); |
| 234 |
| 230 url_loader_->FollowRedirect(); | 235 url_loader_->FollowRedirect(); |
| 231 } | 236 } |
| 232 | 237 |
| 233 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the | 238 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the |
| 234 // caller. | 239 // caller. |
| 235 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() { | 240 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() { |
| 236 return std::move(subresource_url_loader_factory_ptr_info_); | 241 return std::move(subresource_url_loader_factory_ptr_info_); |
| 237 } | 242 } |
| 238 | 243 |
| 239 private: | 244 private: |
| 240 // mojom::URLLoaderClient implementation: | 245 // mojom::URLLoaderClient implementation: |
| 241 void OnReceiveResponse( | 246 void OnReceiveResponse( |
| 242 const ResourceResponseHead& head, | 247 const ResourceResponseHead& head, |
| 243 const base::Optional<net::SSLInfo>& ssl_info, | 248 const base::Optional<net::SSLInfo>& ssl_info, |
| 244 mojom::DownloadedTempFilePtr downloaded_file) override { | 249 mojom::DownloadedTempFilePtr downloaded_file) override { |
| 250 received_response_ = true; |
| 251 // If the default loader (network) was used to handle the URL load request |
| 252 // we need to see if the handlers want to potentially create a new loader |
| 253 // for the response. e.g. AppCache. |
| 254 if (MaybeCreateLoaderForResponse(head)) |
| 255 return; |
| 256 |
| 245 BrowserThread::PostTask( | 257 BrowserThread::PostTask( |
| 246 BrowserThread::UI, FROM_HERE, | 258 BrowserThread::UI, FROM_HERE, |
| 247 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, | 259 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, |
| 248 owner_, head, ssl_info, base::Passed(&downloaded_file))); | 260 owner_, head, ssl_info, base::Passed(&downloaded_file))); |
| 249 } | 261 } |
| 250 | 262 |
| 251 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, | 263 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, |
| 252 const ResourceResponseHead& head) override { | 264 const ResourceResponseHead& head) override { |
| 253 BrowserThread::PostTask( | 265 BrowserThread::PostTask( |
| 254 BrowserThread::UI, FROM_HERE, | 266 BrowserThread::UI, FROM_HERE, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 270 mojo::ScopedDataPipeConsumerHandle body) override { | 282 mojo::ScopedDataPipeConsumerHandle body) override { |
| 271 BrowserThread::PostTask( | 283 BrowserThread::PostTask( |
| 272 BrowserThread::UI, FROM_HERE, | 284 BrowserThread::UI, FROM_HERE, |
| 273 base::Bind( | 285 base::Bind( |
| 274 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, | 286 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, |
| 275 owner_, base::Passed(&body))); | 287 owner_, base::Passed(&body))); |
| 276 } | 288 } |
| 277 | 289 |
| 278 void OnComplete( | 290 void OnComplete( |
| 279 const ResourceRequestCompletionStatus& completion_status) override { | 291 const ResourceRequestCompletionStatus& completion_status) override { |
| 292 if (completion_status.error_code != net::OK && !received_response_) { |
| 293 // If the default loader (network) was used to handle the URL load |
| 294 // request we need to see if the handlers want to potentially create a |
| 295 // new loader for the response. e.g. AppCache. |
| 296 if (MaybeCreateLoaderForResponse(ResourceResponseHead())) |
| 297 return; |
| 298 } |
| 280 BrowserThread::PostTask( | 299 BrowserThread::PostTask( |
| 281 BrowserThread::UI, FROM_HERE, | 300 BrowserThread::UI, FROM_HERE, |
| 282 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, | 301 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, |
| 283 completion_status)); | 302 completion_status)); |
| 284 } | 303 } |
| 285 | 304 |
| 305 // Returns true if a handler wants to handle the response, i.e. return a |
| 306 // different response. For e.g. AppCache may have fallback content to be |
| 307 // returned for a TLD. |
| 308 bool MaybeCreateLoaderForResponse(const ResourceResponseHead& response) { |
| 309 if (!default_loader_used_) |
| 310 return false; |
| 311 |
| 312 // URLLoaderClient request pointer for response loaders, i.e loaders created |
| 313 // for handing responses received from the network URLLoader. |
| 314 mojom::URLLoaderClientRequest response_client_request; |
| 315 |
| 316 for (size_t index = 0; index < handlers_.size(); ++index) { |
| 317 if (handlers_[index]->MaybeCreateLoaderForResponse( |
| 318 response, &response_url_loader_, &response_client_request)) { |
| 319 OnResponseHandlerFound(std::move(response_client_request)); |
| 320 return true; |
| 321 } |
| 322 } |
| 323 return false; |
| 324 } |
| 325 |
| 326 // Called if we find a handler who delivers different content for the URL. |
| 327 void OnResponseHandlerFound( |
| 328 mojom::URLLoaderClientRequest response_client_request) { |
| 329 response_loader_binding_.Bind(std::move(response_client_request)); |
| 330 // We reset this flag as we expect a new response from the handler. |
| 331 default_loader_used_ = false; |
| 332 // Disconnect from the network loader to stop receiving further data |
| 333 // or notifications for the URL. |
| 334 url_loader_->DisconnectClient(); |
| 335 } |
| 336 |
| 286 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; | 337 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; |
| 287 size_t handler_index_ = 0; | 338 size_t handler_index_ = 0; |
| 288 | 339 |
| 289 std::unique_ptr<ResourceRequest> resource_request_; | 340 std::unique_ptr<ResourceRequest> resource_request_; |
| 290 ResourceContext* resource_context_; | 341 ResourceContext* resource_context_; |
| 291 base::Callback<WebContents*()> web_contents_getter_; | 342 base::Callback<WebContents*()> web_contents_getter_; |
| 292 | 343 |
| 293 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_; | 344 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_; |
| 294 | 345 |
| 295 mojom::URLLoaderFactoryPtr webui_factory_ptr_; | 346 mojom::URLLoaderFactoryPtr webui_factory_ptr_; |
| 296 | 347 |
| 297 std::unique_ptr<ThrottlingURLLoader> url_loader_; | 348 std::unique_ptr<ThrottlingURLLoader> url_loader_; |
| 298 | 349 |
| 299 BlobHandles blob_handles_; | 350 BlobHandles blob_handles_; |
| 300 | 351 |
| 301 // Currently used by the AppCache loader to pass its factory to the | 352 // Currently used by the AppCache loader to pass its factory to the |
| 302 // renderer which enables it to handle subresources. | 353 // renderer which enables it to handle subresources. |
| 303 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_; | 354 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_; |
| 304 | 355 |
| 305 // This is referenced only on the UI thread. | 356 // This is referenced only on the UI thread. |
| 306 base::WeakPtr<NavigationURLLoaderNetworkService> owner_; | 357 base::WeakPtr<NavigationURLLoaderNetworkService> owner_; |
| 307 | 358 |
| 359 // Set to true if the default URLLoader (network service) was used for the |
| 360 // current navigation. |
| 361 bool default_loader_used_ = false; |
| 362 |
| 363 // URLLoaderClient binding for loaders created for responses received from the |
| 364 // network loader. |
| 365 mojo::Binding<mojom::URLLoaderClient> response_loader_binding_; |
| 366 |
| 367 // URLLoader instance for response loaders, i.e loaders created for handing |
| 368 // responses received from the network URLLoader. |
| 369 mojom::URLLoaderPtr response_url_loader_; |
| 370 |
| 371 // Set to true if we receive a valid response from a URLLoader, i.e. |
| 372 // URLLoaderClient::OnReceivedResponse() is called. |
| 373 bool received_response_ = false; |
| 374 |
| 308 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); | 375 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); |
| 309 }; | 376 }; |
| 310 | 377 |
| 311 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( | 378 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| 312 ResourceContext* resource_context, | 379 ResourceContext* resource_context, |
| 313 StoragePartition* storage_partition, | 380 StoragePartition* storage_partition, |
| 314 std::unique_ptr<NavigationRequestInfo> request_info, | 381 std::unique_ptr<NavigationRequestInfo> request_info, |
| 315 std::unique_ptr<NavigationUIData> navigation_ui_data, | 382 std::unique_ptr<NavigationUIData> navigation_ui_data, |
| 316 ServiceWorkerNavigationHandle* service_worker_navigation_handle, | 383 ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
| 317 AppCacheNavigationHandle* appcache_handle, | 384 AppCacheNavigationHandle* appcache_handle, |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", | 520 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", |
| 454 this, "&NavigationURLLoaderNetworkService", this, | 521 this, "&NavigationURLLoaderNetworkService", this, |
| 455 "success", false); | 522 "success", false); |
| 456 | 523 |
| 457 delegate_->OnRequestFailed(completion_status.exists_in_cache, | 524 delegate_->OnRequestFailed(completion_status.exists_in_cache, |
| 458 completion_status.error_code); | 525 completion_status.error_code); |
| 459 } | 526 } |
| 460 } | 527 } |
| 461 | 528 |
| 462 } // namespace content | 529 } // namespace content |
| OLD | NEW |