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 main_job_is_blocked_(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 MaybeResumeMainJob(job, base::TimeDelta()); | |
| 228 | |
| 226 if (job_bound_ && bound_job_ != job) { | 229 if (job_bound_ && bound_job_ != job) { |
| 227 // We have bound a job to the associated Request, |job| has been orphaned. | 230 // We have bound a job to the associated Request, |job| has been orphaned. |
| 228 OnOrphanedJobComplete(job); | 231 OnOrphanedJobComplete(job); |
| 229 return; | 232 return; |
| 230 } | 233 } |
| 231 | 234 |
| 232 if (!request_) | 235 if (!request_) |
| 233 return; | 236 return; |
| 234 DCHECK_NE(OK, status); | 237 DCHECK_NE(OK, status); |
| 235 DCHECK(job); | 238 DCHECK(job); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 255 } | 258 } |
| 256 | 259 |
| 257 request_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); | 260 request_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); |
| 258 } | 261 } |
| 259 | 262 |
| 260 void HttpStreamFactoryImpl::JobController::OnCertificateError( | 263 void HttpStreamFactoryImpl::JobController::OnCertificateError( |
| 261 Job* job, | 264 Job* job, |
| 262 int status, | 265 int status, |
| 263 const SSLConfig& used_ssl_config, | 266 const SSLConfig& used_ssl_config, |
| 264 const SSLInfo& ssl_info) { | 267 const SSLInfo& ssl_info) { |
| 268 MaybeResumeMainJob(job, base::TimeDelta()); | |
| 269 | |
| 265 if (job_bound_ && bound_job_ != job) { | 270 if (job_bound_ && bound_job_ != job) { |
| 266 // We have bound a job to the associated Request, |job| has been orphaned. | 271 // We have bound a job to the associated Request, |job| has been orphaned. |
| 267 OnOrphanedJobComplete(job); | 272 OnOrphanedJobComplete(job); |
| 268 return; | 273 return; |
| 269 } | 274 } |
| 270 | 275 |
| 271 if (!request_) | 276 if (!request_) |
| 272 return; | 277 return; |
| 273 DCHECK_NE(OK, status); | 278 DCHECK_NE(OK, status); |
| 274 if (!bound_job_) | 279 if (!bound_job_) |
| 275 BindJob(job); | 280 BindJob(job); |
| 276 | 281 |
| 277 request_->OnCertificateError(status, used_ssl_config, ssl_info); | 282 request_->OnCertificateError(status, used_ssl_config, ssl_info); |
| 278 } | 283 } |
| 279 | 284 |
| 280 void HttpStreamFactoryImpl::JobController::OnHttpsProxyTunnelResponse( | 285 void HttpStreamFactoryImpl::JobController::OnHttpsProxyTunnelResponse( |
| 281 Job* job, | 286 Job* job, |
| 282 const HttpResponseInfo& response_info, | 287 const HttpResponseInfo& response_info, |
| 283 const SSLConfig& used_ssl_config, | 288 const SSLConfig& used_ssl_config, |
| 284 const ProxyInfo& used_proxy_info, | 289 const ProxyInfo& used_proxy_info, |
| 285 HttpStream* stream) { | 290 HttpStream* stream) { |
| 291 MaybeResumeMainJob(job, base::TimeDelta()); | |
| 292 | |
| 286 if (job_bound_ && bound_job_ != job) { | 293 if (job_bound_ && bound_job_ != job) { |
| 287 // We have bound a job to the associated Request, |job| has been orphaned. | 294 // We have bound a job to the associated Request, |job| has been orphaned. |
| 288 OnOrphanedJobComplete(job); | 295 OnOrphanedJobComplete(job); |
| 289 return; | 296 return; |
| 290 } | 297 } |
| 291 | 298 |
| 292 if (!bound_job_) | 299 if (!bound_job_) |
| 293 BindJob(job); | 300 BindJob(job); |
| 294 if (!request_) | 301 if (!request_) |
| 295 return; | 302 return; |
| 296 request_->OnHttpsProxyTunnelResponse(response_info, used_ssl_config, | 303 request_->OnHttpsProxyTunnelResponse(response_info, used_ssl_config, |
| 297 used_proxy_info, stream); | 304 used_proxy_info, stream); |
| 298 } | 305 } |
| 299 | 306 |
| 300 void HttpStreamFactoryImpl::JobController::OnNeedsClientAuth( | 307 void HttpStreamFactoryImpl::JobController::OnNeedsClientAuth( |
| 301 Job* job, | 308 Job* job, |
| 302 const SSLConfig& used_ssl_config, | 309 const SSLConfig& used_ssl_config, |
| 303 SSLCertRequestInfo* cert_info) { | 310 SSLCertRequestInfo* cert_info) { |
| 311 MaybeResumeMainJob(job, base::TimeDelta()); | |
| 312 | |
| 304 if (job_bound_ && bound_job_ != job) { | 313 if (job_bound_ && bound_job_ != job) { |
| 305 // We have bound a job to the associated Request, |job| has been orphaned. | 314 // We have bound a job to the associated Request, |job| has been orphaned. |
| 306 OnOrphanedJobComplete(job); | 315 OnOrphanedJobComplete(job); |
| 307 return; | 316 return; |
| 308 } | 317 } |
| 309 if (!request_) | 318 if (!request_) |
| 310 return; | 319 return; |
| 311 if (!bound_job_) | 320 if (!bound_job_) |
| 312 BindJob(job); | 321 BindJob(job); |
| 313 | 322 |
| 314 request_->OnNeedsClientAuth(used_ssl_config, cert_info); | 323 request_->OnNeedsClientAuth(used_ssl_config, cert_info); |
| 315 } | 324 } |
| 316 | 325 |
| 317 void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth( | 326 void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth( |
| 318 Job* job, | 327 Job* job, |
| 319 const HttpResponseInfo& proxy_response, | 328 const HttpResponseInfo& proxy_response, |
| 320 const SSLConfig& used_ssl_config, | 329 const SSLConfig& used_ssl_config, |
| 321 const ProxyInfo& used_proxy_info, | 330 const ProxyInfo& used_proxy_info, |
| 322 HttpAuthController* auth_controller) { | 331 HttpAuthController* auth_controller) { |
| 332 MaybeResumeMainJob(job, base::TimeDelta()); | |
| 333 | |
| 323 if (job_bound_ && bound_job_ != job) { | 334 if (job_bound_ && bound_job_ != job) { |
| 324 // We have bound a job to the associated Request, |job| has been orphaned. | 335 // We have bound a job to the associated Request, |job| has been orphaned. |
| 325 OnOrphanedJobComplete(job); | 336 OnOrphanedJobComplete(job); |
| 326 return; | 337 return; |
| 327 } | 338 } |
| 328 | 339 |
| 329 if (!request_) | 340 if (!request_) |
| 330 return; | 341 return; |
| 331 if (!bound_job_) | 342 if (!bound_job_) |
| 332 BindJob(job); | 343 BindJob(job); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 used_proxy_info, was_npn_negotiated, | 403 used_proxy_info, was_npn_negotiated, |
| 393 protocol_negotiated, using_spdy, net_log); | 404 protocol_negotiated, using_spdy, net_log); |
| 394 } | 405 } |
| 395 if (is_job_orphaned) { | 406 if (is_job_orphaned) { |
| 396 OnOrphanedJobComplete(job); | 407 OnOrphanedJobComplete(job); |
| 397 } | 408 } |
| 398 } | 409 } |
| 399 | 410 |
| 400 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { | 411 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { |
| 401 DCHECK_EQ(main_job_.get(), job); | 412 DCHECK_EQ(main_job_.get(), job); |
| 413 DCHECK(!bound_job_); | |
| 402 main_job_.reset(); | 414 main_job_.reset(); |
| 403 factory_->OnPreconnectsCompleteInternal(); | 415 factory_->OnPreconnectsCompleteInternal(); |
| 404 MaybeNotifyFactoryOfCompletion(); | 416 MaybeNotifyFactoryOfCompletion(); |
| 405 } | 417 } |
| 406 | 418 |
| 407 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( | 419 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( |
| 408 const Job* job) { | 420 const Job* job) { |
| 409 if (job->job_type() == MAIN) { | 421 if (job->job_type() == MAIN) { |
| 410 DCHECK_EQ(main_job_.get(), job); | 422 DCHECK_EQ(main_job_.get(), job); |
| 411 main_job_.reset(); | 423 main_job_.reset(); |
| 412 } else { | 424 } else { |
| 413 DCHECK_EQ(alternative_job_.get(), job); | 425 DCHECK_EQ(alternative_job_.get(), job); |
| 414 alternative_job_.reset(); | 426 alternative_job_.reset(); |
| 415 } | 427 } |
| 416 | 428 |
| 417 MaybeNotifyFactoryOfCompletion(); | 429 MaybeNotifyFactoryOfCompletion(); |
| 418 } | 430 } |
| 419 | 431 |
| 420 void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest( | 432 void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest( |
| 421 Job* job, | 433 Job* job, |
| 422 const ConnectionAttempts& attempts) { | 434 const ConnectionAttempts& attempts) { |
| 423 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) | 435 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) |
| 424 return; | 436 return; |
| 425 | 437 |
| 426 DCHECK(request_); | 438 DCHECK(request_); |
| 427 request_->AddConnectionAttempts(attempts); | 439 request_->AddConnectionAttempts(attempts); |
| 428 } | 440 } |
| 429 | 441 |
| 442 void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob( | |
| 443 Job* job, | |
| 444 const base::TimeDelta& delay) { | |
| 445 DCHECK(job == main_job_.get() || job == alternative_job_.get()); | |
| 446 if (!main_job_is_blocked_) | |
| 447 return; | |
| 448 | |
| 449 if (job == alternative_job_.get() && main_job_) { | |
| 450 main_job_is_blocked_ = false; | |
| 451 main_job_->Resume(delay); | |
| 452 } | |
| 453 } | |
| 454 | |
| 455 void HttpStreamFactoryImpl::JobController::OnConnectionInitialized(Job* job, | |
| 456 int rv) { | |
| 457 if (rv != OK && rv != ERR_SPDY_SESSION_ALREADY_EXISTS) { | |
|
Ryan Hamilton
2016/07/01 00:13:30
I'm surprised to see the SPDY_SESSION_ALREADY_EXIS
Zhongyi Shi
2016/07/11 23:04:57
Sure. This is refactored from the old code. In the
| |
| 458 // Resume the main job as there's an error raised in connection | |
| 459 // initiation except the case where we find an existing SPDY session for | |
| 460 // this Job. | |
| 461 return MaybeResumeMainJob(job, main_job_wait_time_); | |
| 462 } | |
| 463 } | |
| 464 | |
| 465 bool HttpStreamFactoryImpl::JobController::ShouldWait(Job* job) const { | |
| 466 base::WeakPtrFactory<Job> ptr_factory(job); | |
| 467 // The alternative job never waits. | |
| 468 if (job == alternative_job_.get()) | |
| 469 return false; | |
| 470 | |
| 471 if (!main_job_is_blocked_ && main_job_wait_time_.is_zero()) | |
| 472 return false; | |
| 473 | |
| 474 if (!main_job_wait_time_.is_zero()) { | |
| 475 job->Resume(main_job_wait_time_); | |
| 476 } | |
| 477 return true; | |
| 478 } | |
| 479 | |
| 430 void HttpStreamFactoryImpl::JobController::SetSpdySessionKey( | 480 void HttpStreamFactoryImpl::JobController::SetSpdySessionKey( |
| 431 Job* job, | 481 Job* job, |
| 432 const SpdySessionKey& spdy_session_key) { | 482 const SpdySessionKey& spdy_session_key) { |
| 433 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) | 483 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) |
| 434 return; | 484 return; |
| 435 | 485 |
| 436 DCHECK(request_); | 486 DCHECK(request_); |
| 437 if (!request_->HasSpdySessionKey()) { | 487 if (!request_->HasSpdySessionKey()) { |
| 438 RequestSet& request_set = | 488 RequestSet& request_set = |
| 439 factory_->spdy_session_request_map_[spdy_session_key]; | 489 factory_->spdy_session_request_map_[spdy_session_key]; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 469 } | 519 } |
| 470 | 520 |
| 471 const BoundNetLog* HttpStreamFactoryImpl::JobController::GetNetLog( | 521 const BoundNetLog* HttpStreamFactoryImpl::JobController::GetNetLog( |
| 472 Job* job) const { | 522 Job* job) const { |
| 473 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) | 523 if (is_preconnect_ || (job_bound_ && bound_job_ != job)) |
| 474 return nullptr; | 524 return nullptr; |
| 475 DCHECK(request_); | 525 DCHECK(request_); |
| 476 return &request_->net_log(); | 526 return &request_->net_log(); |
| 477 } | 527 } |
| 478 | 528 |
| 529 bool HttpStreamFactoryImpl::JobController::main_job_is_blocked() { | |
| 530 return main_job_is_blocked_; | |
| 531 } | |
| 532 | |
| 533 const base::TimeDelta& | |
| 534 HttpStreamFactoryImpl::JobController::wait_time_for_main_job() const { | |
| 535 return main_job_wait_time_; | |
| 536 } | |
| 537 | |
| 538 void HttpStreamFactoryImpl::JobController::set_wait_time_for_main_job( | |
| 539 const base::TimeDelta& delay) { | |
| 540 main_job_wait_time_ = delay; | |
| 541 } | |
| 542 | |
| 479 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: | 543 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: |
| 480 JobController::websocket_handshake_stream_create_helper() { | 544 JobController::websocket_handshake_stream_create_helper() { |
| 481 DCHECK(request_); | 545 DCHECK(request_); |
| 482 return request_->websocket_handshake_stream_create_helper(); | 546 return request_->websocket_handshake_stream_create_helper(); |
| 483 } | 547 } |
| 484 | 548 |
| 485 void HttpStreamFactoryImpl::JobController::CreateJobs( | 549 void HttpStreamFactoryImpl::JobController::CreateJobs( |
| 486 const HttpRequestInfo& request_info, | 550 const HttpRequestInfo& request_info, |
| 487 RequestPriority priority, | 551 RequestPriority priority, |
| 488 const SSLConfig& server_ssl_config, | 552 const SSLConfig& server_ssl_config, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 514 HostPortPair alternative_destination(alternative_service.host_port_pair()); | 578 HostPortPair alternative_destination(alternative_service.host_port_pair()); |
| 515 ignore_result( | 579 ignore_result( |
| 516 ApplyHostMappingRules(request_info.url, &alternative_destination)); | 580 ApplyHostMappingRules(request_info.url, &alternative_destination)); |
| 517 | 581 |
| 518 alternative_job_.reset(job_factory_->CreateJob( | 582 alternative_job_.reset(job_factory_->CreateJob( |
| 519 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | 583 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, |
| 520 proxy_ssl_config, alternative_destination, origin_url, | 584 proxy_ssl_config, alternative_destination, origin_url, |
| 521 alternative_service, net_log.net_log())); | 585 alternative_service, net_log.net_log())); |
| 522 AttachJob(alternative_job_.get()); | 586 AttachJob(alternative_job_.get()); |
| 523 | 587 |
| 524 main_job_->WaitFor(alternative_job_.get()); | 588 main_job_is_blocked_ = 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()); | 589 alternative_job_->Start(request_->stream_type()); |
| 529 } | 590 } |
| 530 // Even if |alternative_job| has already finished, it will not have notified | 591 // 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 | 592 // the request yet, since we defer that to the next iteration of the |
| 532 // MessageLoop, so starting |main_job_| is always safe. | 593 // MessageLoop, so starting |main_job_| is always safe. |
| 533 main_job_->Start(request_->stream_type()); | 594 main_job_->Start(request_->stream_type()); |
| 534 } | 595 } |
| 535 | 596 |
| 536 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { | 597 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { |
| 537 DCHECK(job); | 598 DCHECK(job); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 812 first_alternative_service = alternative_service; | 873 first_alternative_service = alternative_service; |
| 813 } | 874 } |
| 814 | 875 |
| 815 // Ask delegate to mark QUIC as broken for the origin. | 876 // Ask delegate to mark QUIC as broken for the origin. |
| 816 if (quic_advertised && quic_all_broken && delegate != nullptr) | 877 if (quic_advertised && quic_all_broken && delegate != nullptr) |
| 817 delegate->OnQuicBroken(); | 878 delegate->OnQuicBroken(); |
| 818 | 879 |
| 819 return first_alternative_service; | 880 return first_alternative_service; |
| 820 } | 881 } |
| 821 } | 882 } |
| OLD | NEW |