| Index: net/quic/core/quic_session.cc
 | 
| diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
 | 
| index 3afc985adf101ab9bbfab38163fd287a2c6921b8..7c1bf263417842c0957aeb5482dd6e935d23f0eb 100644
 | 
| --- a/net/quic/core/quic_session.cc
 | 
| +++ b/net/quic/core/quic_session.cc
 | 
| @@ -45,10 +45,15 @@ QuicSession::QuicSession(QuicConnection* connection,
 | 
|                         perspective() == Perspective::IS_SERVER,
 | 
|                         nullptr),
 | 
|        currently_writing_stream_id_(0),
 | 
| -      respect_goaway_(true) {}
 | 
| +      respect_goaway_(true),
 | 
| +      use_stream_notifier_(
 | 
| +          FLAGS_quic_reloadable_flag_quic_use_stream_notifier) {}
 | 
|  
 | 
|  void QuicSession::Initialize() {
 | 
|    connection_->set_visitor(this);
 | 
| +  if (use_stream_notifier_) {
 | 
| +    connection_->SetStreamNotifier(this);
 | 
| +  }
 | 
|    connection_->SetFromConfig(config_);
 | 
|  
 | 
|    DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id());
 | 
| @@ -66,6 +71,7 @@ QuicSession::~QuicSession() {
 | 
|        << "Surprisingly high number of locally closed self initiated streams"
 | 
|           "still waiting for final byte offset: "
 | 
|        << GetNumLocallyClosedOutgoingStreamsHighestOffset();
 | 
| +  QUIC_LOG_IF(WARNING, !zombie_streams_.empty()) << "Still have zombie streams";
 | 
|  }
 | 
|  
 | 
|  void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
 | 
| @@ -129,6 +135,13 @@ void QuicSession::OnConnectionClosed(QuicErrorCode error,
 | 
|      }
 | 
|    }
 | 
|  
 | 
| +  // Cleanup zombie stream map on connection close.
 | 
| +  while (!zombie_streams_.empty()) {
 | 
| +    ZombieStreamMap::iterator it = zombie_streams_.begin();
 | 
| +    closed_streams_.push_back(std::move(it->second));
 | 
| +    zombie_streams_.erase(it);
 | 
| +  }
 | 
| +
 | 
|    if (visitor_) {
 | 
|      visitor_->OnConnectionClosed(connection_->connection_id(), error,
 | 
|                                   error_details);
 | 
| @@ -369,7 +382,11 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
 | 
|      stream->set_rst_sent(true);
 | 
|    }
 | 
|  
 | 
| -  closed_streams_.push_back(std::move(it->second));
 | 
| +  if (stream->IsWaitingForAcks()) {
 | 
| +    zombie_streams_[stream->id()] = std::move(it->second);
 | 
| +  } else {
 | 
| +    closed_streams_.push_back(std::move(it->second));
 | 
| +  }
 | 
|  
 | 
|    // If we haven't received a FIN or RST for this stream, we need to keep track
 | 
|    // of the how many bytes the stream's flow controller believes it has
 | 
| @@ -944,4 +961,45 @@ QuicStream* QuicSession::CreateAndActivateStream(QuicStreamId id) {
 | 
|    return stream_ptr;
 | 
|  }
 | 
|  
 | 
| +void QuicSession::OnStreamDoneWaitingForAcks(QuicStreamId id) {
 | 
| +  auto it = zombie_streams_.find(id);
 | 
| +  if (it == zombie_streams_.end()) {
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  closed_streams_.push_back(std::move(it->second));
 | 
| +  zombie_streams_.erase(it);
 | 
| +}
 | 
| +
 | 
| +QuicStream* QuicSession::GetStream(QuicStreamId id) const {
 | 
| +  auto static_stream = static_stream_map_.find(id);
 | 
| +  if (static_stream != static_stream_map_.end()) {
 | 
| +    return static_stream->second;
 | 
| +  }
 | 
| +  auto active_stream = dynamic_stream_map_.find(id);
 | 
| +  if (active_stream != dynamic_stream_map_.end()) {
 | 
| +    return active_stream->second.get();
 | 
| +  }
 | 
| +  auto zombie_stream = zombie_streams_.find(id);
 | 
| +  if (zombie_stream != zombie_streams_.end()) {
 | 
| +    return zombie_stream->second.get();
 | 
| +  }
 | 
| +  return nullptr;
 | 
| +}
 | 
| +
 | 
| +void QuicSession::OnStreamFrameAcked(const QuicStreamFrame& frame,
 | 
| +                                     QuicTime::Delta ack_delay_time) {
 | 
| +  QuicStream* stream = GetStream(frame.stream_id);
 | 
| +  if (stream != nullptr) {
 | 
| +    stream->OnStreamFrameAcked(frame, ack_delay_time);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
 | 
| +  QuicStream* stream = GetStream(frame.stream_id);
 | 
| +  if (stream != nullptr) {
 | 
| +    stream->OnStreamFrameRetransmitted(frame);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  }  // namespace net
 | 
| 
 |