| Index: net/http/http_stream_factory_impl_job_controller.cc
|
| diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc
|
| index bd3f2e3bd7cdad801af6e1202c231e9f134b909f..96e576474ee6116efd1cfe33d771749fe1eb7366 100644
|
| --- a/net/http/http_stream_factory_impl_job_controller.cc
|
| +++ b/net/http/http_stream_factory_impl_job_controller.cc
|
| @@ -7,6 +7,7 @@
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/strings/string_util.h"
|
| +#include "base/values.h"
|
| #include "net/base/host_mapping_rules.h"
|
| #include "net/http/bidirectional_stream_impl.h"
|
| #include "net/http/transport_security_state.h"
|
| @@ -14,6 +15,15 @@
|
|
|
| namespace net {
|
|
|
| +// Returns parameters associated with the delay of the HTTP stream job.
|
| +std::unique_ptr<base::Value> NetLogHttpStreamJobDelayCallback(
|
| + base::TimeDelta delay,
|
| + NetLogCaptureMode /* capture_mode */) {
|
| + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
|
| + dict->SetInteger("resume_after_ms", static_cast<int>(delay.InMilliseconds()));
|
| + return std::move(dict);
|
| +}
|
| +
|
| HttpStreamFactoryImpl::JobController::JobController(
|
| HttpStreamFactoryImpl* factory,
|
| HttpStreamRequest::Delegate* delegate,
|
| @@ -26,7 +36,9 @@ HttpStreamFactoryImpl::JobController::JobController(
|
| delegate_(delegate),
|
| is_preconnect_(false),
|
| job_bound_(false),
|
| - bound_job_(nullptr) {
|
| + main_job_is_blocked_(false),
|
| + bound_job_(nullptr),
|
| + ptr_factory_(this) {
|
| DCHECK(factory);
|
| }
|
|
|
| @@ -223,6 +235,8 @@ void HttpStreamFactoryImpl::JobController::OnStreamFailed(
|
| int status,
|
| const SSLConfig& used_ssl_config,
|
| SSLFailureState ssl_failure_state) {
|
| + MaybeResumeMainJob(job, base::TimeDelta());
|
| +
|
| if (job_bound_ && bound_job_ != job) {
|
| // We have bound a job to the associated Request, |job| has been orphaned.
|
| OnOrphanedJobComplete(job);
|
| @@ -262,6 +276,8 @@ void HttpStreamFactoryImpl::JobController::OnCertificateError(
|
| int status,
|
| const SSLConfig& used_ssl_config,
|
| const SSLInfo& ssl_info) {
|
| + MaybeResumeMainJob(job, base::TimeDelta());
|
| +
|
| if (job_bound_ && bound_job_ != job) {
|
| // We have bound a job to the associated Request, |job| has been orphaned.
|
| OnOrphanedJobComplete(job);
|
| @@ -283,6 +299,8 @@ void HttpStreamFactoryImpl::JobController::OnHttpsProxyTunnelResponse(
|
| const SSLConfig& used_ssl_config,
|
| const ProxyInfo& used_proxy_info,
|
| HttpStream* stream) {
|
| + MaybeResumeMainJob(job, base::TimeDelta());
|
| +
|
| if (job_bound_ && bound_job_ != job) {
|
| // We have bound a job to the associated Request, |job| has been orphaned.
|
| OnOrphanedJobComplete(job);
|
| @@ -301,6 +319,8 @@ void HttpStreamFactoryImpl::JobController::OnNeedsClientAuth(
|
| Job* job,
|
| const SSLConfig& used_ssl_config,
|
| SSLCertRequestInfo* cert_info) {
|
| + MaybeResumeMainJob(job, base::TimeDelta());
|
| +
|
| if (job_bound_ && bound_job_ != job) {
|
| // We have bound a job to the associated Request, |job| has been orphaned.
|
| OnOrphanedJobComplete(job);
|
| @@ -320,6 +340,8 @@ void HttpStreamFactoryImpl::JobController::OnNeedsProxyAuth(
|
| const SSLConfig& used_ssl_config,
|
| const ProxyInfo& used_proxy_info,
|
| HttpAuthController* auth_controller) {
|
| + MaybeResumeMainJob(job, base::TimeDelta());
|
| +
|
| if (job_bound_ && bound_job_ != job) {
|
| // We have bound a job to the associated Request, |job| has been orphaned.
|
| OnOrphanedJobComplete(job);
|
| @@ -399,6 +421,7 @@ void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
|
|
|
| void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) {
|
| DCHECK_EQ(main_job_.get(), job);
|
| + DCHECK(!bound_job_);
|
| main_job_.reset();
|
| factory_->OnPreconnectsCompleteInternal();
|
| MaybeNotifyFactoryOfCompletion();
|
| @@ -427,6 +450,63 @@ void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest(
|
| request_->AddConnectionAttempts(attempts);
|
| }
|
|
|
| +void HttpStreamFactoryImpl::JobController::ResumeMainJob() {
|
| + main_job_->net_log().AddEvent(
|
| + NetLog::TYPE_HTTP_STREAM_JOB_DELAYED,
|
| + base::Bind(&NetLogHttpStreamJobDelayCallback, main_job_wait_time_));
|
| +
|
| + main_job_->Resume();
|
| + main_job_wait_time_ = base::TimeDelta();
|
| +}
|
| +
|
| +void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob(
|
| + Job* job,
|
| + const base::TimeDelta& delay) {
|
| + DCHECK(job == main_job_.get() || job == alternative_job_.get());
|
| + if (!main_job_is_blocked_ || job != alternative_job_.get() || !main_job_)
|
| + return;
|
| +
|
| + main_job_is_blocked_ = false;
|
| +
|
| + if (!main_job_->is_waiting())
|
| + return;
|
| +
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&HttpStreamFactoryImpl::JobController::ResumeMainJob,
|
| + ptr_factory_.GetWeakPtr()),
|
| + main_job_wait_time_);
|
| +}
|
| +
|
| +void HttpStreamFactoryImpl::JobController::OnConnectionInitialized(Job* job,
|
| + int rv) {
|
| + if (rv != OK) {
|
| + // Resume the main job as there's an error raised in connection
|
| + // initiation.
|
| + return MaybeResumeMainJob(job, main_job_wait_time_);
|
| + }
|
| +}
|
| +
|
| +bool HttpStreamFactoryImpl::JobController::ShouldWait(Job* job) {
|
| + // The alternative job never waits.
|
| + if (job == alternative_job_.get())
|
| + return false;
|
| +
|
| + if (main_job_is_blocked_)
|
| + return true;
|
| +
|
| + if (main_job_wait_time_.is_zero())
|
| + return false;
|
| +
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&HttpStreamFactoryImpl::JobController::ResumeMainJob,
|
| + ptr_factory_.GetWeakPtr()),
|
| + main_job_wait_time_);
|
| +
|
| + return true;
|
| +}
|
| +
|
| void HttpStreamFactoryImpl::JobController::SetSpdySessionKey(
|
| Job* job,
|
| const SpdySessionKey& spdy_session_key) {
|
| @@ -476,6 +556,12 @@ const BoundNetLog* HttpStreamFactoryImpl::JobController::GetNetLog(
|
| return &request_->net_log();
|
| }
|
|
|
| +void HttpStreamFactoryImpl::JobController::MaybeSetWaitTimeForMainJob(
|
| + const base::TimeDelta& delay) {
|
| + if (main_job_is_blocked_)
|
| + main_job_wait_time_ = delay;
|
| +}
|
| +
|
| WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl::
|
| JobController::websocket_handshake_stream_create_helper() {
|
| DCHECK(request_);
|
| @@ -521,10 +607,7 @@ void HttpStreamFactoryImpl::JobController::CreateJobs(
|
| alternative_service, net_log.net_log()));
|
| AttachJob(alternative_job_.get());
|
|
|
| - main_job_->WaitFor(alternative_job_.get());
|
| - // Make sure to wait until we call WaitFor(), before starting
|
| - // |alternative_job|, otherwise |alternative_job| will not notify |job|
|
| - // appropriately.
|
| + main_job_is_blocked_ = true;
|
| alternative_job_->Start(request_->stream_type());
|
| }
|
| // Even if |alternative_job| has already finished, it will not have notified
|
|
|