Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 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 "net/http/http_stream_factory_impl_job_controller.h" | 5 #include "net/http/http_stream_factory_impl_job_controller.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "net/base/host_mapping_rules.h" | 10 #include "net/base/host_mapping_rules.h" |
| 11 #include "net/http/bidirectional_stream_impl.h" | 11 #include "net/http/bidirectional_stream_impl.h" |
| 12 #include "net/http/transport_security_state.h" | 12 #include "net/http/transport_security_state.h" |
| 13 #include "net/spdy/spdy_session.h" | 13 #include "net/spdy/spdy_session.h" |
| 14 | 14 |
| 15 namespace net { | 15 namespace net { |
| 16 | 16 |
| 17 HttpStreamFactoryImpl::JobController::JobController( | 17 HttpStreamFactoryImpl::JobController::JobController( |
| 18 HttpStreamFactoryImpl* factory, | 18 HttpStreamFactoryImpl* factory, |
| 19 HttpStreamRequest::Delegate* delegate, | 19 HttpStreamRequest::Delegate* delegate, |
| 20 HttpNetworkSession* session, | 20 HttpNetworkSession* session, |
| 21 JobFactory* job_factory) | 21 JobFactory* job_factory) |
| 22 : factory_(factory), | 22 : factory_(factory), |
| 23 session_(session), | 23 session_(session), |
| 24 job_factory_(job_factory), | 24 job_factory_(job_factory), |
| 25 request_(nullptr), | 25 request_(nullptr), |
| 26 delegate_(delegate), | 26 delegate_(delegate), |
| 27 is_preconnect_(false), | 27 is_preconnect_(false), |
| 28 job_bound_(false), | 28 job_bound_(false), |
| 29 blocking_(false), | |
| 29 bound_job_(nullptr) { | 30 bound_job_(nullptr) { |
| 30 DCHECK(factory); | 31 DCHECK(factory); |
| 31 } | 32 } |
| 32 | 33 |
| 33 HttpStreamFactoryImpl::JobController::~JobController() { | 34 HttpStreamFactoryImpl::JobController::~JobController() { |
| 34 main_job_.reset(); | 35 main_job_.reset(); |
| 35 alternative_job_.reset(); | 36 alternative_job_.reset(); |
| 36 bound_job_ = nullptr; | 37 bound_job_ = nullptr; |
| 37 } | 38 } |
| 38 | 39 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 OnJobSucceeded(job); | 217 OnJobSucceeded(job); |
| 217 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, | 218 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, |
| 218 stream); | 219 stream); |
| 219 } | 220 } |
| 220 | 221 |
| 221 void HttpStreamFactoryImpl::JobController::OnStreamFailed( | 222 void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
| 222 Job* job, | 223 Job* job, |
| 223 int status, | 224 int status, |
| 224 const SSLConfig& used_ssl_config, | 225 const SSLConfig& used_ssl_config, |
| 225 SSLFailureState ssl_failure_state) { | 226 SSLFailureState ssl_failure_state) { |
| 227 MaybeResumeOtherJob(job, base::TimeDelta()); | |
|
Ryan Hamilton
2016/06/29 23:12:28
Looks like the other places this is called there i
Zhongyi Shi
2016/06/30 22:53:39
Done.
| |
| 226 if (job_bound_ && bound_job_ != job) { | 228 if (job_bound_ && bound_job_ != job) { |
| 227 // We have bound a job to the associated Request, |job| has been orphaned. | 229 // We have bound a job to the associated Request, |job| has been orphaned. |
| 228 OnOrphanedJobComplete(job); | 230 OnOrphanedJobComplete(job); |
| 229 return; | 231 return; |
| 230 } | 232 } |
| 231 | 233 |
| 232 if (!request_) | 234 if (!request_) |
| 233 return; | 235 return; |
| 234 DCHECK_NE(OK, status); | 236 DCHECK_NE(OK, status); |
| 235 DCHECK(job); | 237 DCHECK(job); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 255 } | 257 } |
| 256 | 258 |
| 257 request_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); | 259 request_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); |
| 258 } | 260 } |
| 259 | 261 |
| 260 void HttpStreamFactoryImpl::JobController::OnCertificateError( | 262 void HttpStreamFactoryImpl::JobController::OnCertificateError( |
| 261 Job* job, | 263 Job* job, |
| 262 int status, | 264 int status, |
| 263 const SSLConfig& used_ssl_config, | 265 const SSLConfig& used_ssl_config, |
| 264 const SSLInfo& ssl_info) { | 266 const SSLInfo& ssl_info) { |
| 267 MaybeResumeOtherJob(job, base::TimeDelta()); | |
| 268 | |
| 265 if (job_bound_ && bound_job_ != job) { | 269 if (job_bound_ && bound_job_ != job) { |
| 266 // We have bound a job to the associated Request, |job| has been orphaned. | 270 // We have bound a job to the associated Request, |job| has been orphaned. |
| 267 OnOrphanedJobComplete(job); | 271 OnOrphanedJobComplete(job); |
| 268 return; | 272 return; |
| 269 } | 273 } |
| 270 | 274 |
| 271 if (!request_) | 275 if (!request_) |
| 272 return; | 276 return; |
| 273 DCHECK_NE(OK, status); | 277 DCHECK_NE(OK, status); |
| 274 if (!bound_job_) | 278 if (!bound_job_) |
| 275 BindJob(job); | 279 BindJob(job); |
| 276 | 280 |
| 277 request_->OnCertificateError(status, used_ssl_config, ssl_info); | 281 request_->OnCertificateError(status, used_ssl_config, ssl_info); |
| 278 } | 282 } |
| 279 | 283 |
| 280 void HttpStreamFactoryImpl::JobController::OnHttpsProxyTunnelResponse( | 284 void HttpStreamFactoryImpl::JobController::OnHttpsProxyTunnelResponse( |
| 281 Job* job, | 285 Job* job, |
| 282 const HttpResponseInfo& response_info, | 286 const HttpResponseInfo& response_info, |
| 283 const SSLConfig& used_ssl_config, | 287 const SSLConfig& used_ssl_config, |
| 284 const ProxyInfo& used_proxy_info, | 288 const ProxyInfo& used_proxy_info, |
| 285 HttpStream* stream) { | 289 HttpStream* stream) { |
| 290 MaybeResumeOtherJob(job, base::TimeDelta()); | |
| 291 | |
| 286 if (job_bound_ && bound_job_ != job) { | 292 if (job_bound_ && bound_job_ != job) { |
| 287 // We have bound a job to the associated Request, |job| has been orphaned. | 293 // We have bound a job to the associated Request, |job| has been orphaned. |
| 288 OnOrphanedJobComplete(job); | 294 OnOrphanedJobComplete(job); |
| 289 return; | 295 return; |
| 290 } | 296 } |
| 291 | 297 |
| 292 if (!bound_job_) | 298 if (!bound_job_) |
| 293 BindJob(job); | 299 BindJob(job); |
| 294 if (!request_) | 300 if (!request_) |
| 295 return; | 301 return; |
| 296 request_->OnHttpsProxyTunnelResponse(response_info, used_ssl_config, | 302 request_->OnHttpsProxyTunnelResponse(response_info, used_ssl_config, |
| 297 used_proxy_info, stream); | 303 used_proxy_info, stream); |
| 298 } | 304 } |
| 299 | 305 |
| 300 void HttpStreamFactoryImpl::JobController::OnNeedsClientAuth( | 306 void HttpStreamFactoryImpl::JobController::OnNeedsClientAuth( |
| 301 Job* job, | 307 Job* job, |
| 302 const SSLConfig& used_ssl_config, | 308 const SSLConfig& used_ssl_config, |
| 303 SSLCertRequestInfo* cert_info) { | 309 SSLCertRequestInfo* cert_info) { |
| 310 MaybeResumeOtherJob(job, base::TimeDelta()); | |
| 311 | |
| 304 if (job_bound_ && bound_job_ != job) { | 312 if (job_bound_ && bound_job_ != job) { |
| 305 // We have bound a job to the associated Request, |job| has been orphaned. | 313 // We have bound a job to the associated Request, |job| has been orphaned. |
| 306 OnOrphanedJobComplete(job); | 314 OnOrphanedJobComplete(job); |
| 307 return; | 315 return; |
| 308 } | 316 } |
| 309 if (!request_) | 317 if (!request_) |
| 310 return; | 318 return; |
| 311 if (!bound_job_) | 319 if (!bound_job_) |
| 312 BindJob(job); | 320 BindJob(job); |
| 313 | 321 |
| 314 request_->OnNeedsClientAuth(used_ssl_config, cert_info); | 322 request_->OnNeedsClientAuth(used_ssl_config, cert_info); |
| 315 } | 323 } |
| 316 | 324 |
| 317 void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth( | 325 void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth( |
| 318 Job* job, | 326 Job* job, |
| 319 const HttpResponseInfo& proxy_response, | 327 const HttpResponseInfo& proxy_response, |
| 320 const SSLConfig& used_ssl_config, | 328 const SSLConfig& used_ssl_config, |
| 321 const ProxyInfo& used_proxy_info, | 329 const ProxyInfo& used_proxy_info, |
| 322 HttpAuthController* auth_controller) { | 330 HttpAuthController* auth_controller) { |
| 331 MaybeResumeOtherJob(job, base::TimeDelta()); | |
|
Ryan Hamilton
2016/06/29 23:12:28
ditto.
Zhongyi Shi
2016/06/30 22:53:39
Done.
| |
| 323 if (job_bound_ && bound_job_ != job) { | 332 if (job_bound_ && bound_job_ != job) { |
| 324 // We have bound a job to the associated Request, |job| has been orphaned. | 333 // We have bound a job to the associated Request, |job| has been orphaned. |
| 325 OnOrphanedJobComplete(job); | 334 OnOrphanedJobComplete(job); |
| 326 return; | 335 return; |
| 327 } | 336 } |
| 328 | 337 |
| 329 if (!request_) | 338 if (!request_) |
| 330 return; | 339 return; |
| 331 if (!bound_job_) | 340 if (!bound_job_) |
| 332 BindJob(job); | 341 BindJob(job); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 used_proxy_info, was_npn_negotiated, | 401 used_proxy_info, was_npn_negotiated, |
| 393 protocol_negotiated, using_spdy, net_log); | 402 protocol_negotiated, using_spdy, net_log); |
| 394 } | 403 } |
| 395 if (is_job_orphaned) { | 404 if (is_job_orphaned) { |
| 396 OnOrphanedJobComplete(job); | 405 OnOrphanedJobComplete(job); |
| 397 } | 406 } |
| 398 } | 407 } |
| 399 | 408 |
| 400 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { | 409 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { |
| 401 DCHECK_EQ(main_job_.get(), job); | 410 DCHECK_EQ(main_job_.get(), job); |
| 411 DCHECK(!bound_job_); | |
| 402 main_job_.reset(); | 412 main_job_.reset(); |
| 403 factory_->OnPreconnectsCompleteInternal(); | 413 factory_->OnPreconnectsCompleteInternal(); |
| 404 MaybeNotifyFactoryOfCompletion(); | 414 MaybeNotifyFactoryOfCompletion(); |
| 405 } | 415 } |
| 406 | 416 |
| 407 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( | 417 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( |
| 408 const Job* job) { | 418 const Job* job) { |
| 409 if (job->job_type() == MAIN) { | 419 if (job->job_type() == MAIN) { |
| 410 DCHECK_EQ(main_job_.get(), job); | 420 DCHECK_EQ(main_job_.get(), job); |
| 411 main_job_.reset(); | 421 main_job_.reset(); |
| 412 } else { | 422 } else { |
| 413 DCHECK_EQ(alternative_job_.get(), job); | 423 DCHECK_EQ(alternative_job_.get(), job); |
| 414 alternative_job_.reset(); | 424 alternative_job_.reset(); |
| 415 } | 425 } |
| 416 | 426 |
| 417 MaybeNotifyFactoryOfCompletion(); | 427 MaybeNotifyFactoryOfCompletion(); |
| 418 } | 428 } |
| 419 | 429 |
| 420 void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest( | 430 void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest( |
| 421 Job* job, | 431 Job* job, |
| 422 const ConnectionAttempts& attempts) { | 432 const ConnectionAttempts& attempts) { |
| 423 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) | 433 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) |
| 424 return; | 434 return; |
| 425 | 435 |
| 426 DCHECK(request_); | 436 DCHECK(request_); |
| 427 request_->AddConnectionAttempts(attempts); | 437 request_->AddConnectionAttempts(attempts); |
| 428 } | 438 } |
| 429 | 439 |
| 440 void HttpStreamFactoryImpl::JobController::MaybeResumeOtherJob( | |
| 441 Job* job, | |
| 442 const base::TimeDelta& delay) { | |
| 443 DCHECK(job == main_job_.get() || job == alternative_job_.get()); | |
| 444 if (!blocking_) | |
| 445 return; | |
| 446 | |
| 447 if (job == alternative_job_.get() && main_job_) { | |
| 448 blocking_ = false; | |
| 449 main_job_->Resume(delay); | |
|
Ryan Hamilton
2016/06/29 23:12:28
I'm confused about when wait_time_ is used to resu
| |
| 450 } | |
| 451 } | |
| 452 | |
| 453 void HttpStreamFactoryImpl::JobController::OnInitConnectionNotSuccessful( | |
| 454 Job* job, | |
| 455 const base::TimeDelta& delay) { | |
| 456 return MaybeResumeOtherJob(job, delay); | |
| 457 } | |
| 458 | |
| 459 bool HttpStreamFactoryImpl::JobController::ShoudWait(Job* job) const { | |
| 460 base::WeakPtrFactory<Job> ptr_factory(job); | |
| 461 if (wait_time_.is_zero()) { | |
| 462 if (job->job_type() == ALTERNATIVE || !blocking_) { | |
| 463 // There is no blocking job and there is no |wait_time_|. | |
| 464 return false; | |
| 465 } | |
| 466 } else { | |
| 467 DCHECK(job->job_type() == ALTERNATIVE || !blocking_); | |
| 468 job->ResumeAfterDelay(wait_time_); | |
| 469 } | |
| 470 return true; | |
| 471 } | |
| 472 | |
| 430 void HttpStreamFactoryImpl::JobController::SetSpdySessionKey( | 473 void HttpStreamFactoryImpl::JobController::SetSpdySessionKey( |
| 431 Job* job, | 474 Job* job, |
| 432 const SpdySessionKey& spdy_session_key) { | 475 const SpdySessionKey& spdy_session_key) { |
| 433 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) | 476 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) |
| 434 return; | 477 return; |
| 435 | 478 |
| 436 DCHECK(request_); | 479 DCHECK(request_); |
| 437 if (!request_->HasSpdySessionKey()) { | 480 if (!request_->HasSpdySessionKey()) { |
| 438 RequestSet& request_set = | 481 RequestSet& request_set = |
| 439 factory_->spdy_session_request_map_[spdy_session_key]; | 482 factory_->spdy_session_request_map_[spdy_session_key]; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 469 } | 512 } |
| 470 | 513 |
| 471 const BoundNetLog* HttpStreamFactoryImpl::JobController::GetNetLog( | 514 const BoundNetLog* HttpStreamFactoryImpl::JobController::GetNetLog( |
| 472 Job* job) const { | 515 Job* job) const { |
| 473 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) | 516 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) |
| 474 return nullptr; | 517 return nullptr; |
| 475 DCHECK(request_); | 518 DCHECK(request_); |
| 476 return &request_->net_log(); | 519 return &request_->net_log(); |
| 477 } | 520 } |
| 478 | 521 |
| 522 const base::TimeDelta& | |
| 523 HttpStreamFactoryImpl::JobController::wait_time_for_main_job() const { | |
| 524 return wait_time_; | |
| 525 } | |
| 526 | |
| 527 void HttpStreamFactoryImpl::JobController::set_wait_time_for_main_job( | |
| 528 const base::TimeDelta& delay) { | |
| 529 wait_time_ = delay; | |
| 530 } | |
| 531 | |
| 532 bool HttpStreamFactoryImpl::JobController::blocking() { | |
| 533 return blocking_; | |
| 534 } | |
| 535 | |
| 479 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: | 536 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: |
| 480 JobController::websocket_handshake_stream_create_helper() { | 537 JobController::websocket_handshake_stream_create_helper() { |
| 481 DCHECK(request_); | 538 DCHECK(request_); |
| 482 return request_->websocket_handshake_stream_create_helper(); | 539 return request_->websocket_handshake_stream_create_helper(); |
| 483 } | 540 } |
| 484 | 541 |
| 485 void HttpStreamFactoryImpl::JobController::CreateJobs( | 542 void HttpStreamFactoryImpl::JobController::CreateJobs( |
| 486 const HttpRequestInfo& request_info, | 543 const HttpRequestInfo& request_info, |
| 487 RequestPriority priority, | 544 RequestPriority priority, |
| 488 const SSLConfig& server_ssl_config, | 545 const SSLConfig& server_ssl_config, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 514 HostPortPair alternative_destination(alternative_service.host_port_pair()); | 571 HostPortPair alternative_destination(alternative_service.host_port_pair()); |
| 515 ignore_result( | 572 ignore_result( |
| 516 ApplyHostMappingRules(request_info.url, &alternative_destination)); | 573 ApplyHostMappingRules(request_info.url, &alternative_destination)); |
| 517 | 574 |
| 518 alternative_job_.reset(job_factory_->CreateJob( | 575 alternative_job_.reset(job_factory_->CreateJob( |
| 519 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | 576 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, |
| 520 proxy_ssl_config, alternative_destination, origin_url, | 577 proxy_ssl_config, alternative_destination, origin_url, |
| 521 alternative_service, net_log.net_log())); | 578 alternative_service, net_log.net_log())); |
| 522 AttachJob(alternative_job_.get()); | 579 AttachJob(alternative_job_.get()); |
| 523 | 580 |
| 524 main_job_->WaitFor(alternative_job_.get()); | 581 blocking_ = true; |
| 525 // Make sure to wait until we call WaitFor(), before starting | |
| 526 // |alternative_job|, otherwise |alternative_job| will not notify |job| | |
| 527 // appropriately. | |
| 528 alternative_job_->Start(request_->stream_type()); | 582 alternative_job_->Start(request_->stream_type()); |
| 529 } | 583 } |
| 530 // Even if |alternative_job| has already finished, it will not have notified | 584 // Even if |alternative_job| has already finished, it will not have notified |
| 531 // the request yet, since we defer that to the next iteration of the | 585 // the request yet, since we defer that to the next iteration of the |
| 532 // MessageLoop, so starting |main_job_| is always safe. | 586 // MessageLoop, so starting |main_job_| is always safe. |
| 533 main_job_->Start(request_->stream_type()); | 587 main_job_->Start(request_->stream_type()); |
| 534 } | 588 } |
| 535 | 589 |
| 536 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { | 590 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { |
| 537 DCHECK(job); | 591 DCHECK(job); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 812 first_alternative_service = alternative_service; | 866 first_alternative_service = alternative_service; |
| 813 } | 867 } |
| 814 | 868 |
| 815 // Ask delegate to mark QUIC as broken for the origin. | 869 // Ask delegate to mark QUIC as broken for the origin. |
| 816 if (quic_advertised && quic_all_broken && delegate != nullptr) | 870 if (quic_advertised && quic_all_broken && delegate != nullptr) |
| 817 delegate->OnQuicBroken(); | 871 delegate->OnQuicBroken(); |
| 818 | 872 |
| 819 return first_alternative_service; | 873 return first_alternative_service; |
| 820 } | 874 } |
| 821 } | 875 } |
| OLD | NEW |