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/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 fallback_response_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; |
| 180 MaybeStartLoader(StartLoaderCallback()); | 181 MaybeStartLoader(StartLoaderCallback(), ResponseFallback()); |
| 181 } | 182 } |
| 182 | 183 |
| 183 void MaybeStartLoader(StartLoaderCallback start_loader_callback) { | 184 void MaybeStartLoader(StartLoaderCallback start_loader_callback, |
| 185 ResponseFallback fallback) { | |
| 184 if (start_loader_callback) { | 186 if (start_loader_callback) { |
| 187 DCHECK(!fallback); | |
| 185 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( | 188 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( |
| 186 std::move(start_loader_callback), | 189 std::move(start_loader_callback), |
| 187 GetContentClient()->browser()->CreateURLLoaderThrottles( | 190 GetContentClient()->browser()->CreateURLLoaderThrottles( |
| 188 web_contents_getter_), | 191 web_contents_getter_), |
| 189 *resource_request_, this, kTrafficAnnotation); | 192 *resource_request_, this, kTrafficAnnotation); |
| 190 | 193 |
| 191 DCHECK_GT(handler_index_, 0U); | 194 DCHECK_GT(handler_index_, 0U); |
| 192 | 195 |
| 193 mojom::URLLoaderFactoryPtr subresource_loader_factory = | 196 mojom::URLLoaderFactoryPtr subresource_loader_factory = |
| 194 handlers_[handler_index_ - 1]->MaybeCreateSubresourceFactory(); | 197 handlers_[handler_index_ - 1]->MaybeCreateSubresourceFactory(); |
| 195 if (subresource_loader_factory.get()) { | 198 if (subresource_loader_factory.get()) { |
| 196 subresource_url_loader_factory_ptr_info_ = | 199 subresource_url_loader_factory_ptr_info_ = |
| 197 subresource_loader_factory.PassInterface(); | 200 subresource_loader_factory.PassInterface(); |
| 198 } | 201 } |
| 199 return; | 202 return; |
| 203 } else { | |
| 204 // We only support one fallback handler at any given point. AppCache is | |
| 205 // the only handler which supports fallback responses. | |
| 206 DCHECK(!fallback_handler_); | |
| 207 fallback_handler_ = std::move(fallback); | |
| 200 } | 208 } |
| 201 | 209 |
| 202 if (handler_index_ < handlers_.size()) { | 210 if (handler_index_ < handlers_.size()) { |
| 203 handlers_[handler_index_++]->MaybeCreateLoader( | 211 handlers_[handler_index_++]->MaybeCreateLoader( |
| 204 *resource_request_, resource_context_, | 212 *resource_request_, resource_context_, |
| 205 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader, | 213 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader, |
| 206 base::Unretained(this))); | 214 base::Unretained(this))); |
| 207 return; | 215 return; |
| 208 } | 216 } |
| 209 | 217 |
| 210 mojom::URLLoaderFactory* factory = nullptr; | 218 mojom::URLLoaderFactory* factory = nullptr; |
| 211 DCHECK_EQ(handlers_.size(), handler_index_); | 219 DCHECK_EQ(handlers_.size(), handler_index_); |
| 212 if (resource_request_->url.SchemeIs(url::kBlobScheme)) { | 220 if (resource_request_->url.SchemeIs(url::kBlobScheme)) { |
| 213 factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); | 221 factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); |
| 214 } else { | 222 } else { |
| 215 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); | 223 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); |
| 224 default_loader_used_ = true; | |
| 216 } | 225 } |
| 217 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( | 226 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( |
| 218 factory, | 227 factory, |
| 219 GetContentClient()->browser()->CreateURLLoaderThrottles( | 228 GetContentClient()->browser()->CreateURLLoaderThrottles( |
| 220 web_contents_getter_), | 229 web_contents_getter_), |
| 221 0 /* routing_id? */, 0 /* request_id? */, | 230 0 /* routing_id? */, 0 /* request_id? */, |
| 222 mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType, | 231 mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType, |
| 223 *resource_request_, this, kTrafficAnnotation); | 232 *resource_request_, this, kTrafficAnnotation); |
| 224 } | 233 } |
| 225 | 234 |
| 226 void FollowRedirect() { | 235 void FollowRedirect() { |
| 227 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 236 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 228 DCHECK(url_loader_); | 237 DCHECK(url_loader_); |
| 229 | 238 |
| 230 url_loader_->FollowRedirect(); | 239 url_loader_->FollowRedirect(); |
| 231 } | 240 } |
| 232 | 241 |
| 233 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the | 242 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the |
| 234 // caller. | 243 // caller. |
| 235 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() { | 244 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() { |
| 236 return std::move(subresource_url_loader_factory_ptr_info_); | 245 return std::move(subresource_url_loader_factory_ptr_info_); |
| 237 } | 246 } |
| 238 | 247 |
| 239 private: | 248 private: |
| 240 // mojom::URLLoaderClient implementation: | 249 // mojom::URLLoaderClient implementation: |
| 241 void OnReceiveResponse( | 250 void OnReceiveResponse( |
| 242 const ResourceResponseHead& head, | 251 const ResourceResponseHead& head, |
| 243 const base::Optional<net::SSLInfo>& ssl_info, | 252 const base::Optional<net::SSLInfo>& ssl_info, |
| 244 mojom::DownloadedTempFilePtr downloaded_file) override { | 253 mojom::DownloadedTempFilePtr downloaded_file) override { |
| 254 response_ = head; | |
| 255 // If the default loader (network) was used to handle the URL load request | |
| 256 // we need to see if the handlers want to load a fallback for the response. | |
| 257 if (MaybeLoadFallbackForResponse(head)) | |
| 258 return; | |
| 259 | |
| 245 BrowserThread::PostTask( | 260 BrowserThread::PostTask( |
| 246 BrowserThread::UI, FROM_HERE, | 261 BrowserThread::UI, FROM_HERE, |
| 247 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, | 262 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, |
| 248 owner_, head, ssl_info, base::Passed(&downloaded_file))); | 263 owner_, head, ssl_info, base::Passed(&downloaded_file))); |
| 249 } | 264 } |
| 250 | 265 |
| 251 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, | 266 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, |
| 252 const ResourceResponseHead& head) override { | 267 const ResourceResponseHead& head) override { |
| 268 response_ = head; | |
| 269 | |
| 253 BrowserThread::PostTask( | 270 BrowserThread::PostTask( |
| 254 BrowserThread::UI, FROM_HERE, | 271 BrowserThread::UI, FROM_HERE, |
| 255 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, | 272 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, |
| 256 owner_, redirect_info, head)); | 273 owner_, redirect_info, head)); |
| 257 } | 274 } |
| 258 | 275 |
| 259 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {} | 276 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {} |
| 260 | 277 |
| 261 void OnUploadProgress(int64_t current_position, | 278 void OnUploadProgress(int64_t current_position, |
| 262 int64_t total_size, | 279 int64_t total_size, |
| 263 OnUploadProgressCallback callback) override {} | 280 OnUploadProgressCallback callback) override {} |
| 264 | 281 |
| 265 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} | 282 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} |
| 266 | 283 |
| 267 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {} | 284 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {} |
| 268 | 285 |
| 269 void OnStartLoadingResponseBody( | 286 void OnStartLoadingResponseBody( |
| 270 mojo::ScopedDataPipeConsumerHandle body) override { | 287 mojo::ScopedDataPipeConsumerHandle body) override { |
| 271 BrowserThread::PostTask( | 288 BrowserThread::PostTask( |
| 272 BrowserThread::UI, FROM_HERE, | 289 BrowserThread::UI, FROM_HERE, |
| 273 base::Bind( | 290 base::Bind( |
| 274 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, | 291 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, |
| 275 owner_, base::Passed(&body))); | 292 owner_, base::Passed(&body))); |
| 276 } | 293 } |
| 277 | 294 |
| 278 void OnComplete( | 295 void OnComplete( |
| 279 const ResourceRequestCompletionStatus& completion_status) override { | 296 const ResourceRequestCompletionStatus& completion_status) override { |
| 297 // If the default loader (network) was used to handle the URL load request | |
| 298 // we need to see if the handlers want to load a fallback for the response. | |
| 299 if (MaybeLoadFallbackForResponse(response_)) | |
| 300 return; | |
| 301 | |
| 280 BrowserThread::PostTask( | 302 BrowserThread::PostTask( |
| 281 BrowserThread::UI, FROM_HERE, | 303 BrowserThread::UI, FROM_HERE, |
| 282 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, | 304 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, |
| 283 completion_status)); | 305 completion_status)); |
| 284 } | 306 } |
| 285 | 307 |
| 308 // Returns true if a handler returns a fallback response. | |
| 309 bool MaybeLoadFallbackForResponse(const ResourceResponseHead& response) { | |
| 310 mojom::URLLoaderClientPtr fallback_client; | |
| 311 mojom::URLLoaderRequest fallback_request; | |
| 312 if (!CreateFallbackClientAndRequest(&fallback_client, &fallback_request)) | |
| 313 return false; | |
| 314 | |
| 315 // We reset this flag as we expect a response from the fallback handler. | |
| 316 default_loader_used_ = false; | |
| 317 // Disconnect from the network loader to stop receiving further data | |
| 318 // or notifications for the URL. | |
| 319 url_loader_->DisconnectClient(); | |
| 320 | |
| 321 return std::move(fallback_handler_) | |
| 322 .Run(response, std::move(fallback_client), std::move(fallback_request)); | |
|
kinuko
2017/07/27 13:46:26
This fallback code works in a very specific way, w
ananta
2017/07/27 22:07:14
It seems like the method name you suggested in an
| |
| 323 } | |
| 324 | |
| 325 // Creates an instance of the URLLoaderClient interface which can be bound | |
| 326 // to a handler for receiving fallback responses. | |
| 327 // Returns true on success. | |
| 328 bool CreateFallbackClientAndRequest(mojom::URLLoaderClientPtr* client, | |
| 329 mojom::URLLoaderRequest* request) { | |
| 330 // Ignore if we don't have a fallback handler or if the request never went | |
| 331 // to the network loader. | |
| 332 if (!default_loader_used_ || !fallback_handler_) | |
| 333 return false; | |
| 334 fallback_response_binding_.Bind(mojo::MakeRequest(client)); | |
| 335 *request = mojo::MakeRequest(&fallback_url_loader_); | |
| 336 return true; | |
| 337 } | |
| 338 | |
| 286 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; | 339 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; |
| 287 size_t handler_index_ = 0; | 340 size_t handler_index_ = 0; |
| 288 | 341 |
| 289 std::unique_ptr<ResourceRequest> resource_request_; | 342 std::unique_ptr<ResourceRequest> resource_request_; |
| 290 ResourceContext* resource_context_; | 343 ResourceContext* resource_context_; |
| 291 base::Callback<WebContents*()> web_contents_getter_; | 344 base::Callback<WebContents*()> web_contents_getter_; |
| 292 | 345 |
| 293 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_; | 346 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_; |
| 294 | 347 |
| 295 mojom::URLLoaderFactoryPtr webui_factory_ptr_; | 348 mojom::URLLoaderFactoryPtr webui_factory_ptr_; |
| 296 | 349 |
| 297 std::unique_ptr<ThrottlingURLLoader> url_loader_; | 350 std::unique_ptr<ThrottlingURLLoader> url_loader_; |
| 298 | 351 |
| 299 BlobHandles blob_handles_; | 352 BlobHandles blob_handles_; |
| 300 | 353 |
| 301 // Currently used by the AppCache loader to pass its factory to the | 354 // Currently used by the AppCache loader to pass its factory to the |
| 302 // renderer which enables it to handle subresources. | 355 // renderer which enables it to handle subresources. |
| 303 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_; | 356 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_; |
| 304 | 357 |
| 305 // This is referenced only on the UI thread. | 358 // This is referenced only on the UI thread. |
| 306 base::WeakPtr<NavigationURLLoaderNetworkService> owner_; | 359 base::WeakPtr<NavigationURLLoaderNetworkService> owner_; |
| 307 | 360 |
| 361 // Set to true if the default URLLoader (network service) was used for the | |
| 362 // current navigation. | |
| 363 bool default_loader_used_ = false; | |
| 364 | |
| 365 // Contains a copy of the response. | |
| 366 ResourceResponseHead response_; | |
| 367 | |
| 368 // URLLoaderClient binding for handling fallback responses. | |
| 369 mojo::Binding<mojom::URLLoaderClient> fallback_response_binding_; | |
| 370 | |
| 371 // URLLoader instance for fallback responses. | |
| 372 mojom::URLLoaderPtr fallback_url_loader_; | |
| 373 | |
| 374 // Fallback response handler. | |
| 375 ResponseFallback fallback_handler_; | |
| 376 | |
| 308 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); | 377 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); |
| 309 }; | 378 }; |
| 310 | 379 |
| 311 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( | 380 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
| 312 ResourceContext* resource_context, | 381 ResourceContext* resource_context, |
| 313 StoragePartition* storage_partition, | 382 StoragePartition* storage_partition, |
| 314 std::unique_ptr<NavigationRequestInfo> request_info, | 383 std::unique_ptr<NavigationRequestInfo> request_info, |
| 315 std::unique_ptr<NavigationUIData> navigation_ui_data, | 384 std::unique_ptr<NavigationUIData> navigation_ui_data, |
| 316 ServiceWorkerNavigationHandle* service_worker_navigation_handle, | 385 ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
| 317 AppCacheNavigationHandle* appcache_handle, | 386 AppCacheNavigationHandle* appcache_handle, |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 453 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", | 522 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", |
| 454 this, "&NavigationURLLoaderNetworkService", this, | 523 this, "&NavigationURLLoaderNetworkService", this, |
| 455 "success", false); | 524 "success", false); |
| 456 | 525 |
| 457 delegate_->OnRequestFailed(completion_status.exists_in_cache, | 526 delegate_->OnRequestFailed(completion_status.exists_in_cache, |
| 458 completion_status.error_code); | 527 completion_status.error_code); |
| 459 } | 528 } |
| 460 } | 529 } |
| 461 | 530 |
| 462 } // namespace content | 531 } // namespace content |
| OLD | NEW |