| Index: net/quic/quic_stream_factory.cc
 | 
| diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
 | 
| index 3e0f4e3a50775605ad5bd8dc06630aef0a7c36dc..34f5aaa11b47c8c74ce3265966440eceefe3b220 100644
 | 
| --- a/net/quic/quic_stream_factory.cc
 | 
| +++ b/net/quic/quic_stream_factory.cc
 | 
| @@ -21,7 +21,6 @@
 | 
|  #include "net/dns/host_resolver.h"
 | 
|  #include "net/dns/single_request_host_resolver.h"
 | 
|  #include "net/http/http_server_properties.h"
 | 
| -#include "net/quic/congestion_control/tcp_receiver.h"
 | 
|  #include "net/quic/crypto/channel_id_chromium.h"
 | 
|  #include "net/quic/crypto/proof_verifier_chromium.h"
 | 
|  #include "net/quic/crypto/quic_random.h"
 | 
| @@ -141,7 +140,7 @@ class QuicStreamFactory::Job {
 | 
|        bool is_https,
 | 
|        bool was_alternate_protocol_recently_broken,
 | 
|        PrivacyMode privacy_mode,
 | 
| -      base::StringPiece method,
 | 
| +      bool is_post,
 | 
|        QuicServerInfo* server_info,
 | 
|        const BoundNetLog& net_log);
 | 
|  
 | 
| @@ -167,15 +166,15 @@ class QuicStreamFactory::Job {
 | 
|  
 | 
|    void OnIOComplete(int rv);
 | 
|  
 | 
| +  void RunAuxilaryJob();
 | 
| +
 | 
| +  void Cancel();
 | 
| +
 | 
|    void CancelWaitForDataReadyCallback();
 | 
|  
 | 
| -  CompletionCallback callback() {
 | 
| -    return callback_;
 | 
| -  }
 | 
| +  const QuicServerId server_id() const { return server_id_; }
 | 
|  
 | 
| -  const QuicServerId server_id() const {
 | 
| -    return server_id_;
 | 
| -  }
 | 
| +  base::WeakPtr<Job> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
 | 
|  
 | 
|   private:
 | 
|    enum IoState {
 | 
| @@ -196,6 +195,7 @@ class QuicStreamFactory::Job {
 | 
|    bool is_post_;
 | 
|    bool was_alternate_protocol_recently_broken_;
 | 
|    scoped_ptr<QuicServerInfo> server_info_;
 | 
| +  bool started_another_job_;
 | 
|    const BoundNetLog net_log_;
 | 
|    QuicClientSession* session_;
 | 
|    CompletionCallback callback_;
 | 
| @@ -212,20 +212,22 @@ QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
 | 
|                              bool is_https,
 | 
|                              bool was_alternate_protocol_recently_broken,
 | 
|                              PrivacyMode privacy_mode,
 | 
| -                            base::StringPiece method,
 | 
| +                            bool is_post,
 | 
|                              QuicServerInfo* server_info,
 | 
|                              const BoundNetLog& net_log)
 | 
|      : io_state_(STATE_RESOLVE_HOST),
 | 
|        factory_(factory),
 | 
|        host_resolver_(host_resolver),
 | 
|        server_id_(host_port_pair, is_https, privacy_mode),
 | 
| -      is_post_(method == "POST"),
 | 
| +      is_post_(is_post),
 | 
|        was_alternate_protocol_recently_broken_(
 | 
|            was_alternate_protocol_recently_broken),
 | 
|        server_info_(server_info),
 | 
| +      started_another_job_(false),
 | 
|        net_log_(net_log),
 | 
|        session_(nullptr),
 | 
| -      weak_factory_(this) {}
 | 
| +      weak_factory_(this) {
 | 
| +}
 | 
|  
 | 
|  QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
 | 
|                              HostResolver* host_resolver,
 | 
| @@ -235,13 +237,18 @@ QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
 | 
|        factory_(factory),
 | 
|        host_resolver_(host_resolver),  // unused
 | 
|        server_id_(server_id),
 | 
| -      is_post_(false),  // unused
 | 
| +      is_post_(false),                                 // unused
 | 
|        was_alternate_protocol_recently_broken_(false),  // unused
 | 
| -      net_log_(session->net_log()),  // unused
 | 
| +      started_another_job_(false),                     // unused
 | 
| +      net_log_(session->net_log()),                    // unused
 | 
|        session_(session),
 | 
| -      weak_factory_(this) {}
 | 
| +      weak_factory_(this) {
 | 
| +}
 | 
|  
 | 
|  QuicStreamFactory::Job::~Job() {
 | 
| +  // If disk cache has a pending WaitForDataReadyCallback, cancel that callback.
 | 
| +  if (server_info_)
 | 
| +    server_info_->ResetWaitForDataReadyCallback();
 | 
|  }
 | 
|  
 | 
|  int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
 | 
| @@ -307,6 +314,19 @@ void QuicStreamFactory::Job::OnIOComplete(int rv) {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +void QuicStreamFactory::Job::RunAuxilaryJob() {
 | 
| +  int rv = Run(base::Bind(&QuicStreamFactory::OnJobComplete,
 | 
| +                          base::Unretained(factory_), this));
 | 
| +  if (rv != ERR_IO_PENDING)
 | 
| +    factory_->OnJobComplete(this, rv);
 | 
| +}
 | 
| +
 | 
| +void QuicStreamFactory::Job::Cancel() {
 | 
| +  callback_.Reset();
 | 
| +  if (session_)
 | 
| +    session_->connection()->SendConnectionClose(QUIC_CONNECTION_CANCELLED);
 | 
| +}
 | 
| +
 | 
|  void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() {
 | 
|    // If we are waiting for WaitForDataReadyCallback, then cancel the callback.
 | 
|    if (io_state_ != STATE_LOAD_SERVER_INFO_COMPLETE)
 | 
| @@ -329,11 +349,9 @@ int QuicStreamFactory::Job::DoResolveHost() {
 | 
|    io_state_ = STATE_RESOLVE_HOST_COMPLETE;
 | 
|    dns_resolution_start_time_ = base::TimeTicks::Now();
 | 
|    return host_resolver_.Resolve(
 | 
| -      HostResolver::RequestInfo(server_id_.host_port_pair()),
 | 
| -      DEFAULT_PRIORITY,
 | 
| +      HostResolver::RequestInfo(server_id_.host_port_pair()), DEFAULT_PRIORITY,
 | 
|        &address_list_,
 | 
| -      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
 | 
| -                 weak_factory_.GetWeakPtr()),
 | 
| +      base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()),
 | 
|        net_log_);
 | 
|  }
 | 
|  
 | 
| @@ -356,7 +374,10 @@ int QuicStreamFactory::Job::DoResolveHostComplete(int rv) {
 | 
|      return OK;
 | 
|    }
 | 
|  
 | 
| -  io_state_ = STATE_LOAD_SERVER_INFO;
 | 
| +  if (server_info_)
 | 
| +    io_state_ = STATE_LOAD_SERVER_INFO;
 | 
| +  else
 | 
| +    io_state_ = STATE_CONNECT;
 | 
|    return OK;
 | 
|  }
 | 
|  
 | 
| @@ -368,8 +389,7 @@ int QuicStreamFactory::Job::DoLoadServerInfo() {
 | 
|  
 | 
|    io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE;
 | 
|  
 | 
| -  if (!server_info_)
 | 
| -    return OK;
 | 
| +  DCHECK(server_info_);
 | 
|  
 | 
|    // To mitigate the effects of disk cache taking too long to load QUIC server
 | 
|    // information, set up a timer to cancel WaitForDataReady's callback.
 | 
| @@ -385,14 +405,20 @@ int QuicStreamFactory::Job::DoLoadServerInfo() {
 | 
|      factory_->task_runner_->PostDelayedTask(
 | 
|          FROM_HERE,
 | 
|          base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback,
 | 
| -                   weak_factory_.GetWeakPtr()),
 | 
| +                   GetWeakPtr()),
 | 
|          base::TimeDelta::FromMilliseconds(load_server_info_timeout_ms));
 | 
|    }
 | 
|  
 | 
|    disk_cache_load_start_time_ = base::TimeTicks::Now();
 | 
| -  return server_info_->WaitForDataReady(
 | 
| -      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
 | 
| -                 weak_factory_.GetWeakPtr()));
 | 
| +  int rv = server_info_->WaitForDataReady(
 | 
| +      base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
 | 
| +  if (rv == ERR_IO_PENDING && factory_->enable_connection_racing()) {
 | 
| +    // If we are waiting to load server config from the disk cache, then start
 | 
| +    // another job.
 | 
| +    started_another_job_ = true;
 | 
| +    factory_->CreateAuxilaryJob(server_id_, is_post_, net_log_);
 | 
| +  }
 | 
| +  return rv;
 | 
|  }
 | 
|  
 | 
|  int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
 | 
| @@ -401,13 +427,20 @@ int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
 | 
|        FROM_HERE_WITH_EXPLICIT_FUNCTION(
 | 
|            "422516 QuicStreamFactory::Job::DoLoadServerInfoComplete"));
 | 
|  
 | 
| -  if (server_info_) {
 | 
| -    UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
 | 
| -                        base::TimeTicks::Now() - disk_cache_load_start_time_);
 | 
| -  }
 | 
| +  UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
 | 
| +                      base::TimeTicks::Now() - disk_cache_load_start_time_);
 | 
|  
 | 
| -  if (rv != OK) {
 | 
| +  if (rv != OK)
 | 
|      server_info_.reset();
 | 
| +
 | 
| +  if (started_another_job_ &&
 | 
| +      (!server_info_ || server_info_->state().server_config.empty() ||
 | 
| +       !factory_->CryptoConfigCacheIsEmpty(server_id_))) {
 | 
| +    // If we have started another job and if we didn't load the server config
 | 
| +    // from the disk cache or if we have received a new server config from the
 | 
| +    // server, then cancel the current job.
 | 
| +    io_state_ = STATE_NONE;
 | 
| +    return ERR_CONNECTION_CLOSED;
 | 
|    }
 | 
|  
 | 
|    io_state_ = STATE_CONNECT;
 | 
| @@ -454,8 +487,7 @@ int QuicStreamFactory::Job::DoConnect() {
 | 
|  
 | 
|    rv = session_->CryptoConnect(
 | 
|        require_confirmation,
 | 
| -      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
 | 
| -                 base::Unretained(this)));
 | 
| +      base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
 | 
|    return rv;
 | 
|  }
 | 
|  
 | 
| @@ -468,8 +500,7 @@ int QuicStreamFactory::Job::DoResumeConnect() {
 | 
|    io_state_ = STATE_CONNECT_COMPLETE;
 | 
|  
 | 
|    int rv = session_->ResumeCryptoConnect(
 | 
| -      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
 | 
| -                 base::Unretained(this)));
 | 
| +      base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
 | 
|  
 | 
|    return rv;
 | 
|  }
 | 
| @@ -564,6 +595,7 @@ QuicStreamFactory::QuicStreamFactory(
 | 
|      int load_server_info_timeout,
 | 
|      float load_server_info_timeout_srtt_multiplier,
 | 
|      bool enable_truncated_connection_ids,
 | 
| +    bool enable_connection_racing,
 | 
|      const QuicTagVector& connection_options)
 | 
|      : require_confirmation_(true),
 | 
|        host_resolver_(host_resolver),
 | 
| @@ -585,11 +617,16 @@ QuicStreamFactory::QuicStreamFactory(
 | 
|        load_server_info_timeout_srtt_multiplier_(
 | 
|            load_server_info_timeout_srtt_multiplier),
 | 
|        enable_truncated_connection_ids_(enable_truncated_connection_ids),
 | 
| +      enable_connection_racing_(enable_connection_racing),
 | 
|        port_seed_(random_generator_->RandUint64()),
 | 
|        check_persisted_supports_quic_(true),
 | 
|        task_runner_(nullptr),
 | 
|        weak_factory_(this) {
 | 
|    DCHECK(transport_security_state_);
 | 
| +  // TODO(michaeln): Remove ScopedTracker below once crbug.com/454983 is fixed
 | 
| +  tracked_objects::ScopedTracker tracking_profile(
 | 
| +      FROM_HERE_WITH_EXPLICIT_FUNCTION(
 | 
| +          "454983 QuicStreamFactory::QuicStreamFactory"));
 | 
|    crypto_config_.set_user_agent_id(user_agent_id);
 | 
|    crypto_config_.AddCanonicalSuffix(".c.youtube.com");
 | 
|    crypto_config_.AddCanonicalSuffix(".googlevideo.com");
 | 
| @@ -610,7 +647,11 @@ QuicStreamFactory::~QuicStreamFactory() {
 | 
|      delete all_sessions_.begin()->first;
 | 
|      all_sessions_.erase(all_sessions_.begin());
 | 
|    }
 | 
| -  STLDeleteValues(&active_jobs_);
 | 
| +  while (!active_jobs_.empty()) {
 | 
| +    const QuicServerId server_id = active_jobs_.begin()->first;
 | 
| +    STLDeleteElements(&(active_jobs_[server_id]));
 | 
| +    active_jobs_.erase(server_id);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  void QuicStreamFactory::set_require_confirmation(bool require_confirmation) {
 | 
| @@ -634,12 +675,16 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
 | 
|    }
 | 
|  
 | 
|    if (HasActiveJob(server_id)) {
 | 
| -    Job* job = active_jobs_[server_id];
 | 
| -    active_requests_[request] = job;
 | 
| -    job_requests_map_[job].insert(request);
 | 
| +    active_requests_[request] = server_id;
 | 
| +    job_requests_map_[server_id].insert(request);
 | 
|      return ERR_IO_PENDING;
 | 
|    }
 | 
|  
 | 
| +  // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
 | 
| +  // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
 | 
| +  if (!task_runner_)
 | 
| +    task_runner_ = base::MessageLoop::current()->message_loop_proxy().get();
 | 
| +
 | 
|    QuicServerInfo* quic_server_info = nullptr;
 | 
|    if (quic_server_info_factory_) {
 | 
|      bool load_from_disk_cache = true;
 | 
| @@ -654,34 +699,22 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
 | 
|          load_from_disk_cache = false;
 | 
|        }
 | 
|      }
 | 
| -    if (load_from_disk_cache) {
 | 
| -      QuicCryptoClientConfig::CachedState* cached =
 | 
| -          crypto_config_.LookupOrCreate(server_id);
 | 
| -      DCHECK(cached);
 | 
| -      if (cached->IsEmpty()) {
 | 
| -        quic_server_info = quic_server_info_factory_->GetForServer(server_id);
 | 
| -      }
 | 
| +    if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) {
 | 
| +      quic_server_info = quic_server_info_factory_->GetForServer(server_id);
 | 
|      }
 | 
|    }
 | 
| -  // TODO(rtenneti): Initialize task_runner_ in the constructor after
 | 
| -  // WebRequestActionWithThreadsTest.* tests are fixed.
 | 
| -  if (!task_runner_)
 | 
| -    task_runner_ = base::MessageLoop::current()->message_loop_proxy().get();
 | 
|  
 | 
| -  bool was_alternate_protocol_recently_broken =
 | 
| -      http_server_properties_ &&
 | 
| -      http_server_properties_->WasAlternateProtocolRecentlyBroken(
 | 
| -          server_id.host_port_pair());
 | 
|    scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, is_https,
 | 
| -                              was_alternate_protocol_recently_broken,
 | 
| -                              privacy_mode, method, quic_server_info, net_log));
 | 
| +                              WasAlternateProtocolRecentlyBroken(server_id),
 | 
| +                              privacy_mode, method == "POST" /* is_post */,
 | 
| +                              quic_server_info, net_log));
 | 
|    int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
 | 
|                                 base::Unretained(this), job.get()));
 | 
| -
 | 
|    if (rv == ERR_IO_PENDING) {
 | 
| -    active_requests_[request] = job.get();
 | 
| -    job_requests_map_[job.get()].insert(request);
 | 
| -    active_jobs_[server_id] = job.release();
 | 
| +    active_requests_[request] = server_id;
 | 
| +    job_requests_map_[server_id].insert(request);
 | 
| +    active_jobs_[server_id].insert(job.release());
 | 
| +    return rv;
 | 
|    }
 | 
|    if (rv == OK) {
 | 
|      DCHECK(HasActiveSession(server_id));
 | 
| @@ -690,6 +723,19 @@ int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
 | 
|    return rv;
 | 
|  }
 | 
|  
 | 
| +void QuicStreamFactory::CreateAuxilaryJob(const QuicServerId server_id,
 | 
| +                                          bool is_post,
 | 
| +                                          const BoundNetLog& net_log) {
 | 
| +  Job* aux_job = new Job(this, host_resolver_, server_id.host_port_pair(),
 | 
| +                         server_id.is_https(),
 | 
| +                         WasAlternateProtocolRecentlyBroken(server_id),
 | 
| +                         server_id.privacy_mode(), is_post, nullptr, net_log);
 | 
| +  active_jobs_[server_id].insert(aux_job);
 | 
| +  task_runner_->PostTask(FROM_HERE,
 | 
| +                         base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob,
 | 
| +                                    aux_job->GetWeakPtr()));
 | 
| +}
 | 
| +
 | 
|  bool QuicStreamFactory::OnResolution(
 | 
|      const QuicServerId& server_id,
 | 
|      const AddressList& address_list) {
 | 
| @@ -715,6 +761,19 @@ bool QuicStreamFactory::OnResolution(
 | 
|  }
 | 
|  
 | 
|  void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
 | 
| +  QuicServerId server_id = job->server_id();
 | 
| +  if (rv != OK) {
 | 
| +    JobSet* jobs = &(active_jobs_[server_id]);
 | 
| +    if (jobs->size() > 1) {
 | 
| +      // If there is another pending job, then we can delete this job and let
 | 
| +      // the other job handle the request.
 | 
| +      job->Cancel();
 | 
| +      jobs->erase(job);
 | 
| +      delete job;
 | 
| +      return;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    if (rv == OK) {
 | 
|      // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
 | 
|      tracked_objects::ScopedTracker tracking_profile1(
 | 
| @@ -725,11 +784,9 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
 | 
|        set_require_confirmation(false);
 | 
|  
 | 
|      // Create all the streams, but do not notify them yet.
 | 
| -    for (RequestSet::iterator it = job_requests_map_[job].begin();
 | 
| -         it != job_requests_map_[job].end() ; ++it) {
 | 
| -      DCHECK(HasActiveSession(job->server_id()));
 | 
| -      (*it)->set_stream(CreateIfSessionExists(job->server_id(),
 | 
| -                                              (*it)->net_log()));
 | 
| +    for (QuicStreamRequest* request : job_requests_map_[server_id]) {
 | 
| +      DCHECK(HasActiveSession(server_id));
 | 
| +      request->set_stream(CreateIfSessionExists(server_id, request->net_log()));
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -738,10 +795,10 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
 | 
|        FROM_HERE_WITH_EXPLICIT_FUNCTION(
 | 
|            "422516 QuicStreamFactory::OnJobComplete2"));
 | 
|  
 | 
| -  while (!job_requests_map_[job].empty()) {
 | 
| -    RequestSet::iterator it = job_requests_map_[job].begin();
 | 
| +  while (!job_requests_map_[server_id].empty()) {
 | 
| +    RequestSet::iterator it = job_requests_map_[server_id].begin();
 | 
|      QuicStreamRequest* request = *it;
 | 
| -    job_requests_map_[job].erase(it);
 | 
| +    job_requests_map_[server_id].erase(it);
 | 
|      active_requests_.erase(request);
 | 
|      // Even though we're invoking callbacks here, we don't need to worry
 | 
|      // about |this| being deleted, because the factory is owned by the
 | 
| @@ -754,10 +811,14 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
 | 
|        FROM_HERE_WITH_EXPLICIT_FUNCTION(
 | 
|            "422516 QuicStreamFactory::OnJobComplete3"));
 | 
|  
 | 
| -  active_jobs_.erase(job->server_id());
 | 
| -  job_requests_map_.erase(job);
 | 
| -  delete job;
 | 
| -  return;
 | 
| +  for (Job* other_job : active_jobs_[server_id]) {
 | 
| +    if (other_job != job)
 | 
| +      other_job->Cancel();
 | 
| +  }
 | 
| +
 | 
| +  STLDeleteElements(&(active_jobs_[server_id]));
 | 
| +  active_jobs_.erase(server_id);
 | 
| +  job_requests_map_.erase(server_id);
 | 
|  }
 | 
|  
 | 
|  // Returns a newly created QuicHttpStream owned by the caller, if a
 | 
| @@ -836,7 +897,7 @@ void QuicStreamFactory::OnSessionConnectTimeout(
 | 
|    QuicServerId server_id = *aliases.begin();
 | 
|    session_aliases_.erase(session);
 | 
|    Job* job = new Job(this, host_resolver_, session, server_id);
 | 
| -  active_jobs_[server_id] = job;
 | 
| +  active_jobs_[server_id].insert(job);
 | 
|    int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
 | 
|                                 base::Unretained(this), job));
 | 
|    DCHECK_EQ(ERR_IO_PENDING, rv);
 | 
| @@ -844,8 +905,8 @@ void QuicStreamFactory::OnSessionConnectTimeout(
 | 
|  
 | 
|  void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
 | 
|    DCHECK(ContainsKey(active_requests_, request));
 | 
| -  Job* job = active_requests_[request];
 | 
| -  job_requests_map_[job].erase(request);
 | 
| +  QuicServerId server_id = active_requests_[request];
 | 
| +  job_requests_map_[server_id].erase(request);
 | 
|    active_requests_.erase(request);
 | 
|  }
 | 
|  
 | 
| @@ -915,6 +976,10 @@ bool QuicStreamFactory::HasActiveSession(
 | 
|    return ContainsKey(active_sessions_, server_id);
 | 
|  }
 | 
|  
 | 
| +bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const {
 | 
| +  return ContainsKey(active_jobs_, key);
 | 
| +}
 | 
| +
 | 
|  int QuicStreamFactory::CreateSession(
 | 
|      const QuicServerId& server_id,
 | 
|      scoped_ptr<QuicServerInfo> server_info,
 | 
| @@ -978,7 +1043,7 @@ int QuicStreamFactory::CreateSession(
 | 
|    // does not consume "too much" memory.  If we see bursty packet loss, we may
 | 
|    // revisit this setting and test for its impact.
 | 
|    const int32 kSocketBufferSize =
 | 
| -      static_cast<int32>(TcpReceiver::kReceiveWindowTCP);
 | 
| +      static_cast<int32>(kDefaultSocketReceiveBuffer);
 | 
|    rv = socket->SetReceiveBufferSize(kSocketBufferSize);
 | 
|    if (rv != OK) {
 | 
|      HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
 | 
| @@ -1098,7 +1163,7 @@ int QuicStreamFactory::CreateSession(
 | 
|    }
 | 
|  
 | 
|    // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
 | 
| -  tracked_objects::ScopedTracker tracking_profile6(
 | 
| +  tracked_objects::ScopedTracker tracking_profile61(
 | 
|        FROM_HERE_WITH_EXPLICIT_FUNCTION(
 | 
|            "422516 QuicStreamFactory::CreateSession61"));
 | 
|  
 | 
| @@ -1107,6 +1172,12 @@ int QuicStreamFactory::CreateSession(
 | 
|        server_info.Pass(), config,
 | 
|        base::MessageLoop::current()->message_loop_proxy().get(),
 | 
|        net_log.net_log());
 | 
| +
 | 
| +  // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
 | 
| +  tracked_objects::ScopedTracker tracking_profile62(
 | 
| +      FROM_HERE_WITH_EXPLICIT_FUNCTION(
 | 
| +          "422516 QuicStreamFactory::CreateSession62"));
 | 
| +
 | 
|    all_sessions_[*session] = server_id;  // owning pointer
 | 
|  
 | 
|    // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
 | 
| @@ -1129,10 +1200,6 @@ int QuicStreamFactory::CreateSession(
 | 
|    return OK;
 | 
|  }
 | 
|  
 | 
| -bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const {
 | 
| -  return ContainsKey(active_jobs_, key);
 | 
| -}
 | 
| -
 | 
|  void QuicStreamFactory::ActivateSession(
 | 
|      const QuicServerId& server_id,
 | 
|      QuicClientSession* session) {
 | 
| @@ -1158,6 +1225,20 @@ int64 QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds(
 | 
|    return stats->srtt.InMicroseconds();
 | 
|  }
 | 
|  
 | 
| +bool QuicStreamFactory::WasAlternateProtocolRecentlyBroken(
 | 
| +    const QuicServerId& server_id) const {
 | 
| +  return http_server_properties_ &&
 | 
| +         http_server_properties_->WasAlternateProtocolRecentlyBroken(
 | 
| +             server_id.host_port_pair());
 | 
| +}
 | 
| +
 | 
| +bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
 | 
| +    const QuicServerId& server_id) {
 | 
| +  QuicCryptoClientConfig::CachedState* cached =
 | 
| +      crypto_config_.LookupOrCreate(server_id);
 | 
| +  return cached->IsEmpty();
 | 
| +}
 | 
| +
 | 
|  void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
 | 
|      const QuicServerId& server_id,
 | 
|      const scoped_ptr<QuicServerInfo>& server_info) {
 | 
| 
 |