Remove stream pointer from QuicSession::WritevData.

The session only uses the pointer to access stream_bytes_written. It could simply be replaced by a |is_retransmission| boolean. This change makes the boundary of streams and sessions clearer.

gfe-relnote: no behavior change, not protected.
PiperOrigin-RevId: 296504335
Change-Id: I349bdadadd923e9dcb5b03231ce351e4f1a25c96
diff --git a/quic/core/http/quic_headers_stream_test.cc b/quic/core/http/quic_headers_stream_test.cc
index 68bbadf..4337318 100644
--- a/quic/core/http/quic_headers_stream_test.cc
+++ b/quic/core/http/quic_headers_stream_test.cc
@@ -286,11 +286,10 @@
                                 SpdyPriority priority,
                                 bool is_request) {
     // Write the headers and capture the outgoing data
-    EXPECT_CALL(session_, WritevData(headers_stream_,
-                                     QuicUtils::GetHeadersStreamId(
+    EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
                                          connection_->transport_version()),
-                                     _, _, NO_FIN))
-        .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
+                                     _, _, NO_FIN, _))
+        .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
     QuicSpdySessionPeer::WriteHeadersOnHeadersStream(
         &session_, stream_id, headers_.Clone(), fin,
         spdy::SpdyStreamPrecedence(priority), nullptr);
@@ -411,11 +410,10 @@
     QuicStreamId promised_stream_id = NextPromisedStreamId();
     if (perspective() == Perspective::IS_SERVER) {
       // Write the headers and capture the outgoing data
-      EXPECT_CALL(session_, WritevData(headers_stream_,
-                                       QuicUtils::GetHeadersStreamId(
+      EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
                                            connection_->transport_version()),
-                                       _, _, NO_FIN))
-          .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
+                                       _, _, NO_FIN, _))
+          .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
       session_.WritePushPromise(stream_id, promised_stream_id,
                                 headers_.Clone());
 
@@ -827,11 +825,10 @@
 }
 
 TEST_P(QuicHeadersStreamTest, AckSentData) {
-  EXPECT_CALL(session_, WritevData(headers_stream_,
-                                   QuicUtils::GetHeadersStreamId(
+  EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
                                        connection_->transport_version()),
-                                   _, _, NO_FIN))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+                                   _, _, NO_FIN, _))
+      .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   InSequence s;
   QuicReferenceCountedPointer<MockAckListener> ack_listener1(
       new MockAckListener());
@@ -897,11 +894,10 @@
 
 TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
   // In this test, a stream frame can contain multiple headers.
-  EXPECT_CALL(session_, WritevData(headers_stream_,
-                                   QuicUtils::GetHeadersStreamId(
+  EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
                                        connection_->transport_version()),
-                                   _, _, NO_FIN))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+                                   _, _, NO_FIN, _))
+      .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   InSequence s;
   QuicReferenceCountedPointer<MockAckListener> ack_listener1(
       new MockAckListener());
@@ -948,11 +944,10 @@
 }
 
 TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
-  EXPECT_CALL(session_, WritevData(headers_stream_,
-                                   QuicUtils::GetHeadersStreamId(
+  EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
                                        connection_->transport_version()),
-                                   _, _, NO_FIN))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+                                   _, _, NO_FIN, _))
+      .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   InSequence s;
   QuicReferenceCountedPointer<MockAckListener> ack_listener1(
       new MockAckListener());
diff --git a/quic/core/http/quic_send_control_stream_test.cc b/quic/core/http/quic_send_control_stream_test.cc
index 1bc10bf..49c5dea 100644
--- a/quic/core/http/quic_send_control_stream_test.cc
+++ b/quic/core/http/quic_send_control_stream_test.cc
@@ -74,7 +74,7 @@
             SupportedVersions(GetParam().version))),
         session_(connection_) {
     ON_CALL(session_, WritevData(_, _, _, _, _))
-        .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+        .WillByDefault(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   }
 
   void Initialize() {
@@ -132,20 +132,22 @@
 
   // A lambda to save and consume stream data when QuicSession::WritevData() is
   // called.
-  auto save_write_data = [&writer](QuicStream* stream, QuicStreamId /*id*/,
-                                   size_t write_length, QuicStreamOffset offset,
-                                   StreamSendingState /*state*/) {
-    stream->WriteStreamData(offset, write_length, &writer);
+  auto save_write_data = [&writer, this](QuicStreamId /*id*/,
+                                         size_t write_length,
+                                         QuicStreamOffset offset,
+                                         StreamSendingState /*state*/,
+                                         bool /*is_retransmission*/) {
+    send_control_stream_->WriteStreamData(offset, write_length, &writer);
     return QuicConsumedData(/* bytes_consumed = */ write_length,
                             /* fin_consumed = */ false);
   };
 
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _, 1, _, _))
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _))
       .WillOnce(Invoke(save_write_data));
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _,
-                                   expected_write_data.size() - 5, _, _))
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(),
+                                   expected_write_data.size() - 5, _, _, _))
       .WillOnce(Invoke(save_write_data));
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _, 4, _, _))
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 4, _, _, _))
       .WillOnce(Invoke(save_write_data));
 
   send_control_stream_->MaybeSendSettingsFrame();
@@ -157,8 +159,9 @@
   Initialize();
   testing::InSequence s;
 
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _, 1, _, _));
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _, _, _, _)).Times(2);
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _));
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _))
+      .Times(2);
   send_control_stream_->MaybeSendSettingsFrame();
 
   // No data should be written the second time MaybeSendSettingsFrame() is
@@ -173,11 +176,12 @@
 
   // The first write will trigger the control stream to write stream type, a
   // SETTINGS frame, and a greased frame before the PRIORITY_UPDATE frame.
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _, _, _, _)).Times(4);
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _))
+      .Times(4);
   PriorityUpdateFrame frame;
   send_control_stream_->WritePriorityUpdate(frame);
 
-  EXPECT_CALL(session_, WritevData(send_control_stream_, _, _, _, _));
+  EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _));
   send_control_stream_->WritePriorityUpdate(frame);
 }
 
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc
index 2ebcbed..01e9fd8 100644
--- a/quic/core/http/quic_spdy_client_session_test.cc
+++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -232,7 +232,7 @@
   // Verify that no data may be send on existing streams.
   char data[] = "hello world";
   QuicConsumedData consumed = session_->WritevData(
-      stream, stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN);
+      stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN, false);
   EXPECT_FALSE(consumed.fin_consumed);
   EXPECT_EQ(0u, consumed.bytes_consumed);
 }
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index fc2f653..bff8bbc 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -267,19 +267,16 @@
     return QuicSpdySession::GetOrCreateStream(stream_id);
   }
 
-  QuicConsumedData WritevData(QuicStream* stream,
-                              QuicStreamId id,
+  QuicConsumedData WritevData(QuicStreamId id,
                               size_t write_length,
                               QuicStreamOffset offset,
-                              StreamSendingState state) override {
+                              StreamSendingState state,
+                              bool is_retransmission) override {
     bool fin = state != NO_FIN;
     QuicConsumedData consumed(write_length, fin);
     if (!writev_consumes_all_data_) {
-      consumed =
-          QuicSession::WritevData(stream, id, write_length, offset, state);
-    }
-    if (fin && consumed.fin_consumed) {
-      stream->set_fin_sent(true);
+      consumed = QuicSession::WritevData(id, write_length, offset, state,
+                                         is_retransmission);
     }
     QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
         id, consumed.bytes_consumed);
@@ -299,7 +296,7 @@
     }
     MakeIOVector("not empty", &iov);
     QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
-    QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
+    QuicConsumedData consumed = WritevData(stream->id(), 9, 0, FIN, false);
     QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
         consumed.bytes_consumed);
     return consumed;
@@ -307,7 +304,7 @@
 
   QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
     DCHECK(writev_consumes_all_data_);
-    return WritevData(stream, stream->id(), bytes, 0, FIN);
+    return WritevData(stream->id(), bytes, 0, FIN, false);
   }
 
   using QuicSession::closed_streams;
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index e68091d..1fca1db 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -203,7 +203,8 @@
     session_ = std::make_unique<StrictMock<MockQuicSpdySession>>(connection_);
     session_->Initialize();
     ON_CALL(*session_, WritevData(_, _, _, _, _))
-        .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+        .WillByDefault(
+            Invoke(session_.get(), &MockQuicSpdySession::ConsumeData));
 
     stream_ =
         new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
@@ -236,17 +237,16 @@
       }
       auto send_control_stream =
           QuicSpdySessionPeer::GetSendControlStream(session_.get());
-      EXPECT_CALL(*session_, WritevData(send_control_stream,
-                                        send_control_stream->id(), _, _, _))
+      EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _))
           .Times(num_control_stream_writes);
       auto qpack_decoder_stream =
           QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
-      EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
-                                        qpack_decoder_stream->id(), 1, 0, _));
+      EXPECT_CALL(*session_,
+                  WritevData(qpack_decoder_stream->id(), 1, 0, _, _));
       auto qpack_encoder_stream =
           QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
-      EXPECT_CALL(*session_, WritevData(qpack_encoder_stream,
-                                        qpack_encoder_stream->id(), 1, 0, _));
+      EXPECT_CALL(*session_,
+                  WritevData(qpack_encoder_stream->id(), 1, 0, _, _));
     }
     static_cast<QuicSession*>(session_.get())
         ->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
@@ -769,7 +769,7 @@
 
   const uint64_t kHeaderLength = UsesHttp3() ? 2 : 0;
   if (UsesHttp3()) {
-    EXPECT_CALL(*session_, WritevData(_, _, kHeaderLength, _, NO_FIN));
+    EXPECT_CALL(*session_, WritevData(_, kHeaderLength, _, NO_FIN, _));
   }
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true)));
@@ -1047,7 +1047,7 @@
   EXPECT_CALL(*connection_,
               SendBlocked(GetNthClientInitiatedBidirectionalId(0)))
       .Times(0);
-  EXPECT_CALL(*session_, WritevData(_, _, 0, _, FIN));
+  EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _));
 
   stream_->WriteOrBufferBody(body, fin);
 }
@@ -1290,8 +1290,7 @@
     // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
     // Four writes on the request stream: HEADERS frame header and payload both
     // for headers and trailers.
-    EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
-        .Times(4);
+    EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(4);
   }
 
   // Write the initial headers, without a FIN.
@@ -1315,14 +1314,13 @@
 
   // Four writes on the request stream: HEADERS frame header and payload both
   // for headers and trailers.
-  EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _)).Times(4);
+  EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(4);
 
   // No PRIORITY_UPDATE frames on the control stream,
   // because the stream has default priority.
   auto send_control_stream =
       QuicSpdySessionPeer::GetSendControlStream(session_.get());
-  EXPECT_CALL(*session_, WritevData(send_control_stream,
-                                    send_control_stream->id(), _, _, _))
+  EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _))
       .Times(0);
 
   // Write the initial headers, without a FIN.
@@ -1345,15 +1343,14 @@
   InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
 
   // Two writes on the request stream: HEADERS frame header and payload.
-  EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _)).Times(2);
+  EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(2);
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
 
   // PRIORITY_UPDATE frame on the control stream.
   auto send_control_stream =
       QuicSpdySessionPeer::GetSendControlStream(session_.get());
-  EXPECT_CALL(*session_, WritevData(send_control_stream,
-                                    send_control_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _));
   stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
 }
 
@@ -1368,15 +1365,14 @@
   // is called, before HEADERS frame is sent.
   auto send_control_stream =
       QuicSpdySessionPeer::GetSendControlStream(session_.get());
-  EXPECT_CALL(*session_, WritevData(send_control_stream,
-                                    send_control_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _));
 
   stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
   testing::Mock::VerifyAndClearExpectations(session_.get());
 
   // Two writes on the request stream: HEADERS frame header and payload.
   // PRIORITY_UPDATE frame is not sent this time, because one is already sent.
-  EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _)).Times(2);
+  EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(2);
   EXPECT_CALL(*stream_, WriteHeadersMock(true));
   stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
 }
@@ -1389,8 +1385,7 @@
   if (UsesHttp3()) {
     // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
     // HEADERS frame header and payload on the request stream.
-    EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
-        .Times(2);
+    EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(2);
   }
 
   // Write the initial headers.
@@ -1433,7 +1428,7 @@
 
   // Expect data being written on the stream.  In addition to that, headers are
   // also written on the stream in case of IETF QUIC.
-  EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
+  EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _))
       .Times(AtLeast(1));
 
   // Write the initial headers.
@@ -1472,9 +1467,9 @@
   // Write non-zero body data, but only consume partially, ensuring queueing.
   const int kBodySize = 1 * 1024;  // 1 kB
   if (UsesHttp3()) {
-    EXPECT_CALL(*session_, WritevData(_, _, 3, _, NO_FIN));
+    EXPECT_CALL(*session_, WritevData(_, 3, _, NO_FIN, _));
   }
-  EXPECT_CALL(*session_, WritevData(_, _, kBodySize, _, NO_FIN))
+  EXPECT_CALL(*session_, WritevData(_, kBodySize, _, NO_FIN, _))
       .WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
   stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
   EXPECT_EQ(1u, stream_->BufferedDataBytes());
@@ -1487,7 +1482,7 @@
   EXPECT_FALSE(stream_->write_side_closed());
 
   // Writing the queued bytes will close the write side of the stream.
-  EXPECT_CALL(*session_, WritevData(_, _, 1, _, NO_FIN));
+  EXPECT_CALL(*session_, WritevData(_, 1, _, NO_FIN, _));
   stream_->OnCanWrite();
   EXPECT_TRUE(stream_->write_side_closed());
 }
@@ -1595,9 +1590,9 @@
   Initialize(kShouldProcessData);
 
   if (UsesHttp3()) {
-    EXPECT_CALL(*session_, WritevData(_, _, 2, _, NO_FIN));
+    EXPECT_CALL(*session_, WritevData(_, 2, _, NO_FIN, _));
   }
-  EXPECT_CALL(*session_, WritevData(_, _, 4, _, FIN));
+  EXPECT_CALL(*session_, WritevData(_, 4, _, FIN, _));
   stream_->WriteOrBufferBody("data", true);
   stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority));
   EXPECT_EQ(spdy::SpdyStreamPrecedence(kV3HighestPriority),
@@ -2029,8 +2024,7 @@
       QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
 
   // The stream byte will be written in the first byte.
-  EXPECT_CALL(*session_, WritevData(decoder_send_stream,
-                                    decoder_send_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _));
   // Deliver dynamic table entry to decoder.
   session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
 
@@ -2052,8 +2046,7 @@
                                          headers.length(), data));
   EXPECT_EQ(kDataFramePayload, stream_->data());
 
-  EXPECT_CALL(*session_, WritevData(decoder_send_stream,
-                                    decoder_send_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _));
   // Deliver second dynamic table entry to decoder.
   session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
 
@@ -2094,8 +2087,7 @@
       QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
 
   // The stream byte will be written in the first byte.
-  EXPECT_CALL(*session_, WritevData(decoder_send_stream,
-                                    decoder_send_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _));
   // Deliver dynamic table entry to decoder.
   session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
   EXPECT_TRUE(stream_->headers_decompressed());
@@ -2120,8 +2112,7 @@
   // Decoding is blocked because dynamic table entry has not been received yet.
   EXPECT_FALSE(stream_->trailers_decompressed());
 
-  EXPECT_CALL(*session_, WritevData(decoder_send_stream,
-                                    decoder_send_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _));
   // Deliver second dynamic table entry to decoder.
   session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
   EXPECT_TRUE(stream_->trailers_decompressed());
@@ -2215,8 +2206,7 @@
       QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
 
   // The stream byte will be written in the first byte.
-  EXPECT_CALL(*session_, WritevData(decoder_send_stream,
-                                    decoder_send_stream->id(), _, _, _));
+  EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _));
   // Deliver dynamic table entry to decoder.
   session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
   EXPECT_TRUE(stream_->headers_decompressed());
@@ -2645,8 +2635,7 @@
 
   auto qpack_decoder_stream =
       QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
-  EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
-                                    qpack_decoder_stream->id(), 1, 1, _));
+  EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _));
   EXPECT_CALL(*session_,
               SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 0));
 
@@ -2664,8 +2653,7 @@
 
   auto qpack_decoder_stream =
       QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
-  EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
-                                    qpack_decoder_stream->id(), 1, 1, _));
+  EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _));
 
   stream_->OnStreamReset(QuicRstStreamFrame(
       kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
diff --git a/quic/core/qpack/qpack_send_stream_test.cc b/quic/core/qpack/qpack_send_stream_test.cc
index ab0f3d7..e3fcc15 100644
--- a/quic/core/qpack/qpack_send_stream_test.cc
+++ b/quic/core/qpack/qpack_send_stream_test.cc
@@ -77,7 +77,7 @@
         QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
 
     ON_CALL(session_, WritevData(_, _, _, _, _))
-        .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+        .WillByDefault(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   }
 
   Perspective perspective() const { return GetParam().perspective; }
@@ -96,11 +96,11 @@
 
 TEST_P(QpackSendStreamTest, WriteStreamTypeOnlyFirstTime) {
   std::string data = "data";
-  EXPECT_CALL(session_, WritevData(_, _, 1, _, _));
-  EXPECT_CALL(session_, WritevData(_, _, data.length(), _, _));
+  EXPECT_CALL(session_, WritevData(_, 1, _, _, _));
+  EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _));
   qpack_send_stream_->WriteStreamData(quiche::QuicheStringPiece(data));
 
-  EXPECT_CALL(session_, WritevData(_, _, data.length(), _, _));
+  EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _));
   qpack_send_stream_->WriteStreamData(quiche::QuicheStringPiece(data));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(0);
   qpack_send_stream_->MaybeSendStreamType();
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index 8a3153d..ba5219a 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -290,8 +290,9 @@
     // Set appropriate encryption level.
     session()->connection()->SetDefaultEncryptionLevel(
         retransmission_encryption_level);
-    QuicConsumedData consumed = stream_delegate()->WritevData(
-        this, id(), pending.length, pending.offset, NO_FIN);
+    QuicConsumedData consumed =
+        stream_delegate()->WritevData(id(), pending.length, pending.offset,
+                                      NO_FIN, /*is_retransmission*/ true);
     QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
                   << " tries to retransmit stream data [" << pending.offset
                   << ", " << pending.offset + pending.length
@@ -333,7 +334,8 @@
     // Set appropriate encryption level.
     session()->connection()->SetDefaultEncryptionLevel(send_encryption_level);
     QuicConsumedData consumed = stream_delegate()->WritevData(
-        this, id(), retransmission_length, retransmission_offset, NO_FIN);
+        id(), retransmission_length, retransmission_offset, NO_FIN,
+        /*is_retransmission*/ true);
     QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
                   << " is forced to retransmit stream data ["
                   << retransmission_offset << ", "
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc
index fd61522..2006e47 100644
--- a/quic/core/quic_crypto_stream_test.cc
+++ b/quic/core/quic_crypto_stream_test.cc
@@ -157,20 +157,18 @@
   std::string data(1350, 'a');
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 0, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 0, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
   // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
   EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 1350, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 1350, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -182,24 +180,21 @@
   stream_->OnStreamFrameLost(1200, 800, false);
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1000, 0, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1000, 0, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   // Verify [1200, 2000) are sent in [1200, 1350) and [1350, 2000) because of
   // they are in different encryption levels.
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 150, 1200, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 150, 1200, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 650, 1350, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 650, 1350, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->OnCanWrite();
   EXPECT_FALSE(stream_->HasPendingRetransmission());
   // Verify connection's encryption level has restored.
@@ -267,20 +262,18 @@
   std::string data(1350, 'a');
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 0, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 0, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
   // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
   EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 1350, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 1350, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
 
   // Lost [0, 1350).
@@ -353,20 +346,18 @@
   std::string data(1350, 'a');
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 0, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 0, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
   // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
   EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 1350, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 1350, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -380,14 +371,12 @@
   // Force crypto stream to send [1350, 2700) and only [1350, 1500) is consumed.
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 650, 1350, _))
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 650, 1350, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(
-            stream_,
+        return session_.ConsumeData(
             QuicUtils::GetCryptoStreamId(connection_->transport_version()), 150,
-            1350, NO_FIN);
+            1350, NO_FIN, 1350);
       }));
 
   EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false));
@@ -397,16 +386,14 @@
   // Force session to send [1350, 1500) again and all data is consumed.
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 650, 1350, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 650, 1350, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 200, 2500, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 200, 2500, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false));
   // Verify connection's encryption level has restored.
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -482,9 +469,8 @@
   std::string data(1350, 'a');
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 0, _))
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 0, _, _))
       .WillOnce(testing::Return(QuicConsumedData(0, false)));
   stream_->WriteOrBufferData(data, false, nullptr);
   EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -494,10 +480,9 @@
 
   EXPECT_CALL(
       session_,
-      WritevData(_,
-                 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
-                 1350, 0, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+                 1350, 0, _, _))
+      .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
   stream_->OnCanWrite();
   EXPECT_TRUE(stream_->IsWaitingForAcks());
   EXPECT_TRUE(session_.HasUnackedCryptoData());
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index fc282d8..c78bb66 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -734,11 +734,11 @@
   connection_->ProcessUdpPacket(self_address, peer_address, packet);
 }
 
-QuicConsumedData QuicSession::WritevData(QuicStream* stream,
-                                         QuicStreamId id,
+QuicConsumedData QuicSession::WritevData(QuicStreamId id,
                                          size_t write_length,
                                          QuicStreamOffset offset,
-                                         StreamSendingState state) {
+                                         StreamSendingState state,
+                                         bool is_retransmission) {
   if (!IsEncryptionEstablished() &&
       !QuicUtils::IsCryptoStreamId(transport_version(), id)) {
     // Do not let streams write without encryption. The calling stream will end
@@ -748,7 +748,7 @@
 
   QuicConsumedData data =
       connection_->SendStreamData(id, write_length, offset, state);
-  if (offset >= stream->stream_bytes_written()) {
+  if (!is_retransmission) {
     // This is new stream data.
     write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
   }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index baf3a14..beb6763 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -268,11 +268,11 @@
   // indicating if the fin bit was consumed.  This does not indicate the data
   // has been sent on the wire: it may have been turned into a packet and queued
   // if the socket was unexpectedly blocked.
-  QuicConsumedData WritevData(QuicStream* stream,
-                              QuicStreamId id,
+  QuicConsumedData WritevData(QuicStreamId id,
                               size_t write_length,
                               QuicStreamOffset offset,
-                              StreamSendingState state) override;
+                              StreamSendingState state,
+                              bool is_retransmission) override;
 
   // Called by the QuicCryptoStream when a handshake message is sent.
   virtual void OnCryptoHandshakeMessageSent(
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 8582b1b..d9ecbae 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -261,19 +261,16 @@
     return GetNumActiveStreams() > 0;
   }
 
-  QuicConsumedData WritevData(QuicStream* stream,
-                              QuicStreamId id,
+  QuicConsumedData WritevData(QuicStreamId id,
                               size_t write_length,
                               QuicStreamOffset offset,
-                              StreamSendingState state) override {
+                              StreamSendingState state,
+                              bool is_retransmission) override {
     bool fin = state != NO_FIN;
     QuicConsumedData consumed(write_length, fin);
     if (!writev_consumes_all_data_) {
-      consumed =
-          QuicSession::WritevData(stream, id, write_length, offset, state);
-    }
-    if (fin && consumed.fin_consumed) {
-      stream->set_fin_sent(true);
+      consumed = QuicSession::WritevData(id, write_length, offset, state,
+                                         is_retransmission);
     }
     QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
         id, consumed.bytes_consumed);
@@ -295,7 +292,8 @@
     }
     MakeIOVector("not empty", &iov);
     QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
-    QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
+    QuicConsumedData consumed =
+        WritevData(stream->id(), 9, 0, FIN, /*is_retransmission*/ false);
     QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
         consumed.bytes_consumed);
     return consumed;
@@ -311,7 +309,8 @@
 
   QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
     DCHECK(writev_consumes_all_data_);
-    return WritevData(stream, stream->id(), bytes, 0, FIN);
+    return WritevData(stream->id(), bytes, 0, FIN,
+                      /*is_retransmission*/ false);
   }
 
   bool UsesPendingStreams() const override { return uses_pending_streams_; }
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc
index ffbc7aa..03b7f4c 100644
--- a/quic/core/quic_stream.cc
+++ b/quic/core/quic_stream.cc
@@ -929,9 +929,9 @@
     const bool can_bundle_fin =
         retransmit_fin && (retransmission_offset + retransmission_length ==
                            stream_bytes_written());
-    consumed = stream_delegate_->WritevData(this, id_, retransmission_length,
-                                            retransmission_offset,
-                                            can_bundle_fin ? FIN : NO_FIN);
+    consumed = stream_delegate_->WritevData(
+        id_, retransmission_length, retransmission_offset,
+        can_bundle_fin ? FIN : NO_FIN, /*is_retransmission*/ true);
     QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                   << " is forced to retransmit stream data ["
                   << retransmission_offset << ", "
@@ -952,8 +952,8 @@
   if (retransmit_fin) {
     QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                   << " retransmits fin only frame.";
-    consumed =
-        stream_delegate_->WritevData(this, id_, 0, stream_bytes_written(), FIN);
+    consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
+                                            /*is_retransmission*/ true);
     if (!consumed.fin_consumed) {
       return false;
     }
@@ -1023,8 +1023,9 @@
   if (fin && add_random_padding_after_fin_) {
     state = FIN_AND_PADDING;
   }
-  QuicConsumedData consumed_data = stream_delegate_->WritevData(
-      this, id(), write_length, stream_bytes_written(), state);
+  QuicConsumedData consumed_data =
+      stream_delegate_->WritevData(id(), write_length, stream_bytes_written(),
+                                   state, /*is_retransmission*/ false);
 
   OnStreamDataConsumed(consumed_data.bytes_consumed);
 
@@ -1098,8 +1099,8 @@
     if (!send_buffer_.HasPendingRetransmission()) {
       QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                     << " retransmits fin only frame.";
-      consumed = stream_delegate_->WritevData(this, id_, 0,
-                                              stream_bytes_written(), FIN);
+      consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(),
+                                              FIN, /*is_retransmission*/ true);
       fin_lost_ = !consumed.fin_consumed;
       if (fin_lost_) {
         // Connection is write blocked.
@@ -1112,9 +1113,9 @@
       const bool can_bundle_fin =
           fin_lost_ &&
           (pending.offset + pending.length == stream_bytes_written());
-      consumed = stream_delegate_->WritevData(this, id_, pending.length,
-                                              pending.offset,
-                                              can_bundle_fin ? FIN : NO_FIN);
+      consumed = stream_delegate_->WritevData(
+          id_, pending.length, pending.offset, can_bundle_fin ? FIN : NO_FIN,
+          /*is_retransmission*/ true);
       QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                     << " tries to retransmit stream data [" << pending.offset
                     << ", " << pending.offset + pending.length
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc
index 0dad1aa..c7e650b 100644
--- a/quic/core/quic_stream_test.cc
+++ b/quic/core/quic_stream_test.cc
@@ -122,11 +122,11 @@
            write_blocked_list_->HasWriteBlockedDataStreams();
   }
 
-  QuicConsumedData CloseStreamOnWriteError(QuicStream* /*stream*/,
-                                           QuicStreamId id,
+  QuicConsumedData CloseStreamOnWriteError(QuicStreamId id,
                                            size_t /*write_length*/,
                                            QuicStreamOffset /*offset*/,
-                                           StreamSendingState /*state*/) {
+                                           StreamSendingState /*state*/,
+                                           QuicByteCount /*bytes_written*/) {
     session_->CloseStream(id);
     return QuicConsumedData(1, false);
   }
@@ -277,8 +277,8 @@
               VARIABLE_LENGTH_INTEGER_LENGTH_0, 0u);
   connection_->SetMaxPacketLength(length);
 
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
-      .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->WriteOrBufferData(kData1, false, nullptr);
   EXPECT_FALSE(HasWriteBlockedStreams());
 }
@@ -299,10 +299,9 @@
 
   // Write some data and no fin.  If we consume some but not all of the data,
   // we should be write blocked a not all the data was consumed.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 1u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false,
                              nullptr);
@@ -318,10 +317,9 @@
   // we should be write blocked because the fin was not consumed.
   // (This should never actually happen as the fin should be sent out with the
   // last data)
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN, false);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
                              nullptr);
@@ -334,7 +332,7 @@
 
   // Write no data and a fin.  If we consume nothing we should be write blocked,
   // as the fin was not consumed.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(0, false)));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(), true, nullptr);
   ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
@@ -346,7 +344,7 @@
   // Write some data and no fin. However, while writing the data
   // close the stream and verify that MarkConnectionLevelWriteBlocked does not
   // crash with an unknown stream.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(Invoke(this, &QuicStreamTest::CloseStreamOnWriteError));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false,
                              nullptr);
@@ -368,8 +366,8 @@
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(),
-                                            kDataLen - 1, 0u, NO_FIN);
+        return session_->ConsumeData(stream_->id(), kDataLen - 1, 0u, NO_FIN,
+                                     false);
       }));
   stream_->WriteOrBufferData(kData1, false, nullptr);
 
@@ -384,8 +382,8 @@
   InSequence s;
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(),
-                                            kDataLen - 1, kDataLen - 1, NO_FIN);
+        return session_->ConsumeData(stream_->id(), kDataLen - 1, kDataLen - 1,
+                                     NO_FIN, false);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData());
   stream_->OnCanWrite();
@@ -394,8 +392,8 @@
   // And finally the end of the bytes_consumed.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u,
-                                            2 * kDataLen - 2, NO_FIN);
+        return session_->ConsumeData(stream_->id(), 2u, 2 * kDataLen - 2,
+                                     NO_FIN, false);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData());
   stream_->OnCanWrite();
@@ -408,7 +406,7 @@
   QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(),
                                         stream_);
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->WriteOrBufferData(data, false, nullptr);
   EXPECT_TRUE(session_->HasUnackedStreamData());
   EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _));
@@ -439,10 +437,9 @@
   EXPECT_FALSE(rst_sent());
 
   // Write some data, with no FIN.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 1u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), false,
                              nullptr);
@@ -468,10 +465,9 @@
   EXPECT_FALSE(rst_sent());
 
   // Write some data, with FIN.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 1u, 0u,
-                                            FIN);
+        return session_->ConsumeData(stream_->id(), 1u, 0u, FIN, false);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), true,
                              nullptr);
@@ -734,10 +730,9 @@
   EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
 
   // Outgoing data with FIN.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u, 0u,
-                                            FIN);
+        return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
                              nullptr);
@@ -753,10 +748,9 @@
   Initialize();
 
   // Outgoing data with FIN.
-  EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+  EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u, 0u,
-                                            FIN);
+        return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
                              nullptr);
@@ -784,7 +778,7 @@
   Initialize();
   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
 
   // Receive data for the request.
   EXPECT_CALL(*stream_, OnDataAvailable()).Times(1);
@@ -806,7 +800,7 @@
 TEST_P(QuicStreamTest, StreamWaitsForAcks) {
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   // Stream is not waiting for acks initially.
   EXPECT_FALSE(stream_->IsWaitingForAcks());
   EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -863,7 +857,7 @@
 TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) {
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   // Send data.
   stream_->WriteOrBufferData(kData1, false, nullptr);
   stream_->WriteOrBufferData(kData1, false, nullptr);
@@ -905,7 +899,7 @@
 TEST_P(QuicStreamTest, CancelStream) {
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_FALSE(stream_->IsWaitingForAcks());
   EXPECT_FALSE(session_->HasUnackedStreamData());
   EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -947,7 +941,7 @@
 
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_FALSE(stream_->IsWaitingForAcks());
   EXPECT_FALSE(session_->HasUnackedStreamData());
   EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -973,7 +967,7 @@
 TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_FALSE(stream_->IsWaitingForAcks());
   EXPECT_FALSE(session_->HasUnackedStreamData());
   EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -996,7 +990,7 @@
 TEST_P(QuicStreamTest, ConnectionClosed) {
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_FALSE(stream_->IsWaitingForAcks());
   EXPECT_FALSE(session_->HasUnackedStreamData());
   EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1032,8 +1026,7 @@
   // Testing WriteOrBufferData.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 100u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false);
       }));
   stream_->WriteOrBufferData(data, false, nullptr);
   stream_->WriteOrBufferData(data, false, nullptr);
@@ -1045,8 +1038,7 @@
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 100, 100u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN, false);
       }));
   // Buffered data size > threshold, do not ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
@@ -1059,8 +1051,8 @@
                          GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(),
-                                            data_to_write, 200u, NO_FIN);
+        return session_->ConsumeData(stream_->id(), data_to_write, 200u, NO_FIN,
+                                     false);
       }));
   // Buffered data size < threshold, ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1072,7 +1064,7 @@
 
   // Flush all buffered data.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
   EXPECT_EQ(0u, stream_->BufferedDataBytes());
@@ -1109,8 +1101,8 @@
       data.length() - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(),
-                                            data_to_write, 0u, NO_FIN);
+        return session_->ConsumeData(stream_->id(), data_to_write, 0u, NO_FIN,
+                                     false);
       }));
 
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1139,7 +1131,7 @@
   QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(),
                                         stream_);
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   struct iovec iov = {const_cast<char*>(data.data()), 5u};
   QuicMemSliceStorage storage(
       &iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
@@ -1171,8 +1163,7 @@
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 100u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false);
       }));
   // There is no buffered data before, all data should be consumed.
   QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
@@ -1193,8 +1184,8 @@
                          GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(),
-                                            data_to_write, 100u, NO_FIN);
+        return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN,
+                                     false);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
@@ -1213,7 +1204,7 @@
 
   // Flush all buffered data.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->OnCanWrite();
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
   EXPECT_FALSE(stream_->HasBufferedData());
@@ -1230,8 +1221,7 @@
   QuicMemSliceSpan span1 = vector1.span();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 5u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN, false);
       }));
   // There is no buffered data before, all data should be consumed.
   QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
@@ -1249,7 +1239,7 @@
 TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
   Initialize();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_FALSE(stream_->IsWaitingForAcks());
   EXPECT_FALSE(session_->HasUnackedStreamData());
 
@@ -1316,7 +1306,7 @@
 
   // Send [0, 9).
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->WriteOrBufferData(kData1, false, nullptr);
   EXPECT_FALSE(stream_->HasBufferedData());
   EXPECT_TRUE(stream_->IsStreamFrameOutstanding(0, 9, false));
@@ -1334,7 +1324,7 @@
   stream_->OnStreamFrameLost(0, 9, false);
   EXPECT_TRUE(stream_->HasPendingRetransmission());
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
   EXPECT_FALSE(stream_->HasPendingRetransmission());
@@ -1342,13 +1332,13 @@
 
   // This OnCanWrite causes [9, 27) to be sent.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->OnCanWrite();
   EXPECT_FALSE(stream_->HasBufferedData());
 
   // Send a fin only frame.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->WriteOrBufferData("", true, nullptr);
 
   // Lost [9, 27) and fin.
@@ -1368,8 +1358,7 @@
   // be bundled with data.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 9u, 18u,
-                                            FIN);
+        return session_->ConsumeData(stream_->id(), 9u, 18u, FIN, false);
       }));
   stream_->OnCanWrite();
   EXPECT_FALSE(stream_->HasPendingRetransmission());
@@ -1385,7 +1374,7 @@
 
   // Send [0, 18) and fin.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->WriteOrBufferData(kData1, false, nullptr);
   stream_->WriteOrBufferData(kData2, true, nullptr);
 
@@ -1398,8 +1387,7 @@
   InSequence s;
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 9u, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN, false);
       }));
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(0, true)));
@@ -1421,7 +1409,7 @@
   session_->ActivateStream(QuicWrapUnique(stream));
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_CALL(*connection_, SendControlFrame(_))
       .WillOnce(Invoke(&ClearControlFrame));
   std::string data(1024, '.');
@@ -1455,7 +1443,7 @@
 
   std::string data(100, '.');
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_CALL(*connection_, SendControlFrame(_))
       .WillOnce(Invoke(&ClearControlFrame));
   stream->WriteOrBufferData(data, false, nullptr);
@@ -1474,9 +1462,9 @@
   InSequence s;
 
   // Send [0, 18) with fin.
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), _, _, _))
+  EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _))
       .Times(2)
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   stream_->WriteOrBufferData(kData1, false, nullptr);
   stream_->WriteOrBufferData(kData1, true, nullptr);
   // Ack [10, 13).
@@ -1485,33 +1473,32 @@
                               QuicTime::Zero(), &newly_acked_length);
   EXPECT_EQ(3u, newly_acked_length);
   // Retransmit [0, 18) with fin, and only [0, 8) is consumed.
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 10, 0, NO_FIN))
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return MockQuicSession::ConsumeData(stream_, stream_->id(), 8, 0u,
-                                            NO_FIN);
+        return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN, false);
       }));
   EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true));
 
   // Retransmit [0, 18) with fin, and all is consumed.
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 10, 0, NO_FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 5, 13, FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 5, 13, FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_TRUE(stream_->RetransmitStreamData(0, 18, true));
 
   // Retransmit [0, 8) with fin, and all is consumed.
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 8, 0, NO_FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 0, 18, FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 8, 0, NO_FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 0, 18, FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_TRUE(stream_->RetransmitStreamData(0, 8, true));
 }
 
 TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
   Initialize();
 
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   std::string body(200, 'a');
   stream_->WriteOrBufferData(body, true, nullptr);
 
@@ -1519,8 +1506,8 @@
   QuicTime::Delta ttl = QuicTime::Delta::FromSeconds(1);
   ASSERT_TRUE(stream_->MaybeSetTtl(ttl));
   // Verify data gets retransmitted because TTL does not expire.
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 100, 0, NO_FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 100, 0, NO_FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_TRUE(stream_->RetransmitStreamData(0, 100, false));
   stream_->OnStreamFrameLost(100, 100, true);
   EXPECT_TRUE(stream_->HasPendingRetransmission());
@@ -1534,8 +1521,8 @@
 TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresEarlyRetransmitData) {
   Initialize();
 
-  EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN))
-      .WillOnce(Invoke(MockQuicSession::ConsumeData));
+  EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _))
+      .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   std::string body(200, 'a');
   stream_->WriteOrBufferData(body, true, nullptr);
 
diff --git a/quic/core/stream_delegate_interface.h b/quic/core/stream_delegate_interface.h
index 81ec92c..2443a74 100644
--- a/quic/core/stream_delegate_interface.h
+++ b/quic/core/stream_delegate_interface.h
@@ -21,11 +21,11 @@
   virtual void OnStreamError(QuicErrorCode error_code,
                              std::string error_details) = 0;
   // Called when the stream needs to write data.
-  virtual QuicConsumedData WritevData(QuicStream* stream,
-                                      QuicStreamId id,
+  virtual QuicConsumedData WritevData(QuicStreamId id,
                                       size_t write_length,
                                       QuicStreamOffset offset,
-                                      StreamSendingState state) = 0;
+                                      StreamSendingState state,
+                                      bool is_retransmission) = 0;
   // Called on stream creation.
   virtual void RegisterStreamPriority(
       QuicStreamId id,
diff --git a/quic/qbone/qbone_stream_test.cc b/quic/qbone/qbone_stream_test.cc
index 71f4260..dcd80bd 100644
--- a/quic/qbone/qbone_stream_test.cc
+++ b/quic/qbone/qbone_stream_test.cc
@@ -40,11 +40,11 @@
   ~MockQuicSession() override {}
 
   // Writes outgoing data from QuicStream to a string.
-  QuicConsumedData WritevData(QuicStream* stream,
-                              QuicStreamId id,
+  QuicConsumedData WritevData(QuicStreamId id,
                               size_t write_length,
                               QuicStreamOffset offset,
-                              StreamSendingState state) override {
+                              StreamSendingState state,
+                              bool is_retransmission) override {
     if (!writable_) {
       return QuicConsumedData(0, false);
     }
diff --git a/quic/quartc/quartc_stream_test.cc b/quic/quartc/quartc_stream_test.cc
index bb0d0e4..3a4e731 100644
--- a/quic/quartc/quartc_stream_test.cc
+++ b/quic/quartc/quartc_stream_test.cc
@@ -64,11 +64,11 @@
   ~MockQuicSession() override {}
 
   // Writes outgoing data from QuicStream to a string.
-  QuicConsumedData WritevData(QuicStream* stream,
-                              QuicStreamId /*id*/,
+  QuicConsumedData WritevData(QuicStreamId id,
                               size_t write_length,
                               QuicStreamOffset offset,
-                              StreamSendingState state) override {
+                              StreamSendingState state,
+                              bool /*is_retransmission*/) override {
     if (!writable_) {
       return QuicConsumedData(0, false);
     }
@@ -77,6 +77,8 @@
     // data is consumed. Retrieve data from stream.
     char* buf = new char[write_length];
     QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
+    QuicStream* stream = GetOrCreateStream(id);
+    DCHECK(stream);
     if (write_length > 0) {
       stream->WriteStreamData(offset, write_length, &writer);
     }
diff --git a/quic/quic_transport/quic_transport_stream_test.cc b/quic/quic_transport/quic_transport_stream_test.cc
index 69d40f4..9fce821 100644
--- a/quic/quic_transport/quic_transport_stream_test.cc
+++ b/quic/quic_transport/quic_transport_stream_test.cc
@@ -141,7 +141,7 @@
   EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
   ASSERT_TRUE(stream_->CanWrite());
 
-  EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
+  EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _))
       .WillOnce(Return(QuicConsumedData(0, /*fin_consumed=*/true)));
   EXPECT_TRUE(stream_->SendFin());
   EXPECT_FALSE(stream_->CanWrite());
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index 4a9bac5..6ba98de 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -22,6 +22,7 @@
 #include "net/third_party/quiche/src/quic/core/quic_framer.h"
 #include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
 #include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -576,14 +577,15 @@
   crypto_stream_.reset(crypto_stream);
 }
 
-// static
-QuicConsumedData MockQuicSession::ConsumeData(QuicStream* stream,
-                                              QuicStreamId /*id*/,
+QuicConsumedData MockQuicSession::ConsumeData(QuicStreamId id,
                                               size_t write_length,
                                               QuicStreamOffset offset,
-                                              StreamSendingState state) {
+                                              StreamSendingState state,
+                                              bool /*is_retransmission*/) {
   if (write_length > 0) {
     auto buf = std::make_unique<char[]>(write_length);
+    QuicStream* stream = GetOrCreateStream(id);
+    DCHECK(stream);
     QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
     stream->WriteStreamData(offset, write_length, &writer);
   } else {
@@ -647,6 +649,23 @@
   crypto_stream_.reset(crypto_stream);
 }
 
+QuicConsumedData MockQuicSpdySession::ConsumeData(QuicStreamId id,
+                                                  size_t write_length,
+                                                  QuicStreamOffset offset,
+                                                  StreamSendingState state,
+                                                  bool /*is_retransmission*/) {
+  if (write_length > 0) {
+    auto buf = std::make_unique<char[]>(write_length);
+    QuicStream* stream = GetOrCreateStream(id);
+    DCHECK(stream);
+    QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
+    stream->WriteStreamData(offset, write_length, &writer);
+  } else {
+    DCHECK(state != NO_FIN);
+  }
+  return QuicConsumedData(write_length, state != NO_FIN);
+}
+
 TestQuicSpdyServerSession::TestQuicSpdyServerSession(
     QuicConnection* connection,
     const QuicConfig& config,
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index 035e15b..7a95250 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -22,6 +22,7 @@
 #include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
 #include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
 #include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
 #include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
@@ -633,11 +634,11 @@
   MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool());
   MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
   MOCK_METHOD5(WritevData,
-               QuicConsumedData(QuicStream* stream,
-                                QuicStreamId id,
+               QuicConsumedData(QuicStreamId id,
                                 size_t write_length,
                                 QuicStreamOffset offset,
-                                StreamSendingState state));
+                                StreamSendingState state,
+                                bool is_retransmission));
 
   MOCK_METHOD3(SendRstStream,
                void(QuicStreamId stream_id,
@@ -663,11 +664,11 @@
 
   // Returns a QuicConsumedData that indicates all of |write_length| (and |fin|
   // if set) has been consumed.
-  static QuicConsumedData ConsumeData(QuicStream* stream,
-                                      QuicStreamId id,
-                                      size_t write_length,
-                                      QuicStreamOffset offset,
-                                      StreamSendingState state);
+  QuicConsumedData ConsumeData(QuicStreamId id,
+                               size_t write_length,
+                               QuicStreamOffset offset,
+                               StreamSendingState state,
+                               bool is_retransmission);
 
   void ReallySendRstStream(QuicStreamId id,
                            QuicRstStreamErrorCode error,
@@ -732,11 +733,11 @@
   MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool());
   MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
   MOCK_METHOD5(WritevData,
-               QuicConsumedData(QuicStream* stream,
-                                QuicStreamId id,
+               QuicConsumedData(QuicStreamId id,
                                 size_t write_length,
                                 QuicStreamOffset offset,
-                                StreamSendingState state));
+                                StreamSendingState state,
+                                bool is_retransmission));
 
   MOCK_METHOD3(SendRstStream,
                void(QuicStreamId stream_id,
@@ -777,6 +778,14 @@
       OnStreamFrameData,
       void(QuicStreamId stream_id, const char* data, size_t len, bool fin));
 
+  // Returns a QuicConsumedData that indicates all of |write_length| (and |fin|
+  // if set) has been consumed.
+  QuicConsumedData ConsumeData(QuicStreamId id,
+                               size_t write_length,
+                               QuicStreamOffset offset,
+                               StreamSendingState state,
+                               bool is_retransmission);
+
   using QuicSession::ActivateStream;
 
  private:
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc
index 6c842fc..880d3aa 100644
--- a/quic/tools/quic_simple_server_stream_test.cc
+++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -110,7 +110,7 @@
       QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
     }
     ON_CALL(*this, WritevData(_, _, _, _, _))
-        .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+        .WillByDefault(Invoke(this, &MockQuicSimpleServerSession::ConsumeData));
   }
 
   MockQuicSimpleServerSession(const MockQuicSimpleServerSession&) = delete;
@@ -123,11 +123,11 @@
                     ConnectionCloseSource source));
   MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
   MOCK_METHOD5(WritevData,
-               QuicConsumedData(QuicStream* stream,
-                                QuicStreamId id,
+               QuicConsumedData(QuicStreamId id,
                                 size_t write_length,
                                 QuicStreamOffset offset,
-                                StreamSendingState state));
+                                StreamSendingState state,
+                                bool is_retransmission));
   MOCK_METHOD4(OnStreamHeaderList,
                void(QuicStreamId stream_id,
                     bool fin,
@@ -163,6 +163,23 @@
 
   MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame));
 
+  QuicConsumedData ConsumeData(QuicStreamId id,
+                               size_t write_length,
+                               QuicStreamOffset offset,
+                               StreamSendingState state,
+                               bool /*is_retransmission*/) {
+    if (write_length > 0) {
+      auto buf = std::make_unique<char[]>(write_length);
+      QuicStream* stream = GetOrCreateStream(id);
+      DCHECK(stream);
+      QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
+      stream->WriteStreamData(offset, write_length, &writer);
+    } else {
+      DCHECK(state != NO_FIN);
+    }
+    return QuicConsumedData(write_length, state != NO_FIN);
+  }
+
   spdy::SpdyHeaderBlock original_request_headers_;
 };
 
@@ -257,7 +274,8 @@
 
 TEST_P(QuicSimpleServerStreamTest, TestFraming) {
   EXPECT_CALL(session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(
+          Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
   stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
   std::unique_ptr<char[]> buffer;
   QuicByteCount header_length =
@@ -274,7 +292,8 @@
 
 TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
   EXPECT_CALL(session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(
+          Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
 
   stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
   std::unique_ptr<char[]> buffer;
@@ -292,7 +311,8 @@
 
 TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) {
   EXPECT_CALL(session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(
+          Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
 
   EXPECT_FALSE(stream_->fin_received());
   EXPECT_FALSE(stream_->rst_received());
@@ -311,9 +331,9 @@
   // We'll automatically write out an error (headers + body)
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, _, kDataFrameHeaderLength, _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _));
   }
-  EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+  EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
 
   EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
 
@@ -362,9 +382,9 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
   }
-  EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+  EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
 
   stream_->DoSendResponse();
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -395,9 +415,9 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
   }
-  EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+  EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
 
   stream_->DoSendResponse();
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -455,9 +475,9 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
   }
-  EXPECT_CALL(session_, WritevData(_, _, body.length(), _, FIN));
+  EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _));
 
   stream_->DoSendResponse();
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -497,9 +517,9 @@
                             _, _));
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _));
   }
-  EXPECT_CALL(session_, WritevData(_, _, body.length(), _, FIN));
+  EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _));
   stream_->DoSendResponse();
   EXPECT_EQ(*request_headers, session_.original_request_headers_);
 }
@@ -553,11 +573,11 @@
   EXPECT_CALL(*server_initiated_stream, WriteHeadersMock(false));
 
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, header_length,
-                                     _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header_length, _,
+                                     NO_FIN, _));
   }
   EXPECT_CALL(session_,
-              WritevData(_, kServerInitiatedStreamId, kBody.size(), _, FIN));
+              WritevData(kServerInitiatedStreamId, kBody.size(), _, FIN, _));
   server_initiated_stream->PushResponse(std::move(headers));
   EXPECT_EQ(kPath, server_initiated_stream->GetHeader(":path"));
   EXPECT_EQ("GET", server_initiated_stream->GetHeader(":method"));
@@ -571,9 +591,9 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, _, kDataFrameHeaderLength, _, NO_FIN));
+    EXPECT_CALL(session_, WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _));
   }
-  EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+  EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _));
 
   stream_->DoSendErrorResponse();
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -590,7 +610,8 @@
 
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(
+          Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
   stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
 
   EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
@@ -608,7 +629,8 @@
 
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _))
-      .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+      .WillRepeatedly(
+          Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
   stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
 
   EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
@@ -642,8 +664,7 @@
     // assumption on their number or size.
     auto* qpack_decoder_stream =
         QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
-    EXPECT_CALL(session_, WritevData(qpack_decoder_stream,
-                                     qpack_decoder_stream->id(), _, _, _))
+    EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _))
         .Times(AnyNumber());
   }
   EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);