Updates Http2Adapter::SubmitRequest/SubmitResponse to include an `end_stream` parameter.

This parameter will be necessary when migrating from the API where the caller passes in a DataFrameSource to one where data is provided via an Http2VisitorInterface method.

This change adds backwards compatibility methods to the interface, which are necessary during the Envoy upstream process.

PiperOrigin-RevId: 630056417
diff --git a/quiche/http2/adapter/adapter_impl_comparison_test.cc b/quiche/http2/adapter/adapter_impl_comparison_test.cc
index aaa2f99..3e4392d 100644
--- a/quiche/http2/adapter/adapter_impl_comparison_test.cc
+++ b/quiche/http2/adapter/adapter_impl_comparison_test.cc
@@ -60,7 +60,7 @@
   const int kConnectionWindowIncrease = 192 * 1024;
 
   const int32_t nghttp2_stream_id =
-      nghttp2_adapter->SubmitRequest(request_headers, nullptr, nullptr);
+      nghttp2_adapter->SubmitRequest(request_headers, nullptr, true, nullptr);
 
   // Both the connection and stream flow control windows are increased.
   nghttp2_adapter->SubmitWindowUpdate(0, kConnectionWindowIncrease);
@@ -73,7 +73,7 @@
             nghttp2_window);
 
   const int32_t oghttp2_stream_id =
-      oghttp2_adapter->SubmitRequest(request_headers, nullptr, nullptr);
+      oghttp2_adapter->SubmitRequest(request_headers, nullptr, true, nullptr);
   // Both the connection and stream flow control windows are increased.
   oghttp2_adapter->SubmitWindowUpdate(0, kConnectionWindowIncrease);
   oghttp2_adapter->SubmitWindowUpdate(oghttp2_stream_id,
diff --git a/quiche/http2/adapter/http2_adapter.h b/quiche/http2/adapter/http2_adapter.h
index 817d4ea..35c9829 100644
--- a/quiche/http2/adapter/http2_adapter.h
+++ b/quiche/http2/adapter/http2_adapter.h
@@ -112,17 +112,35 @@
                                          size_t num_bytes) = 0;
 
   // Returns the assigned stream ID if the operation succeeds. Otherwise,
-  // returns a negative integer indicating an error code. |data_source| may be
-  // nullptr if the request does not have a body.
+  // returns a negative integer indicating an error code. |data_source| should
+  // be nullptr if the request does not have a body. If |end_stream| is true,
+  // the adapter will set the fin bit on the request HEADERS frame.
+  // DEPRECATED in favor of the version with end_headers.
+  int32_t SubmitRequest(absl::Span<const Header> headers,
+                        std::unique_ptr<DataFrameSource> data_source,
+                        void* user_data) {
+    const bool end_headers = (data_source == nullptr);
+    return SubmitRequest(headers, std::move(data_source), end_headers,
+                         user_data);
+  }
   virtual int32_t SubmitRequest(absl::Span<const Header> headers,
                                 std::unique_ptr<DataFrameSource> data_source,
-                                void* user_data) = 0;
+                                bool end_stream, void* user_data) = 0;
 
   // Returns 0 on success. |data_source| may be nullptr if the response does not
-  // have a body.
+  // have a body. If |end_stream| is true, the adapter will set the fin bit on
+  // the response HEADERS frame.
+  // DEPRECATED in favor of the version with end_headers.
+  int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
+                     std::unique_ptr<DataFrameSource> data_source) {
+    const bool end_headers = (data_source == nullptr);
+    return SubmitResponse(stream_id, headers, std::move(data_source),
+                          end_headers);
+  }
   virtual int SubmitResponse(Http2StreamId stream_id,
                              absl::Span<const Header> headers,
-                             std::unique_ptr<DataFrameSource> data_source) = 0;
+                             std::unique_ptr<DataFrameSource> data_source,
+                             bool end_stream) = 0;
 
   // Queues trailers to be sent after any outstanding data on the stream with ID
   // |stream_id|. Returns 0 on success.
diff --git a/quiche/http2/adapter/nghttp2_adapter.cc b/quiche/http2/adapter/nghttp2_adapter.cc
index ded8307..557bd82 100644
--- a/quiche/http2/adapter/nghttp2_adapter.cc
+++ b/quiche/http2/adapter/nghttp2_adapter.cc
@@ -223,7 +223,9 @@
 
 int32_t NgHttp2Adapter::SubmitRequest(
     absl::Span<const Header> headers,
-    std::unique_ptr<DataFrameSource> data_source, void* stream_user_data) {
+    std::unique_ptr<DataFrameSource> data_source, bool end_stream,
+    void* stream_user_data) {
+  QUICHE_DCHECK_EQ(end_stream, data_source == nullptr);
   auto nvs = GetNghttp2Nvs(headers);
   std::unique_ptr<nghttp2_data_provider> provider =
       MakeDataProvider(data_source.get());
@@ -238,9 +240,11 @@
   return stream_id;
 }
 
-int NgHttp2Adapter::SubmitResponse(
-    Http2StreamId stream_id, absl::Span<const Header> headers,
-    std::unique_ptr<DataFrameSource> data_source) {
+int NgHttp2Adapter::SubmitResponse(Http2StreamId stream_id,
+                                   absl::Span<const Header> headers,
+                                   std::unique_ptr<DataFrameSource> data_source,
+                                   bool end_stream) {
+  QUICHE_DCHECK_EQ(end_stream, data_source == nullptr);
   auto nvs = GetNghttp2Nvs(headers);
   std::unique_ptr<nghttp2_data_provider> provider =
       MakeDataProvider(data_source.get());
diff --git a/quiche/http2/adapter/nghttp2_adapter.h b/quiche/http2/adapter/nghttp2_adapter.h
index 9337bb9..6f4b405 100644
--- a/quiche/http2/adapter/nghttp2_adapter.h
+++ b/quiche/http2/adapter/nghttp2_adapter.h
@@ -75,10 +75,11 @@
 
   int32_t SubmitRequest(absl::Span<const Header> headers,
                         std::unique_ptr<DataFrameSource> data_source,
-                        void* user_data) override;
+                        bool end_stream, void* user_data) override;
 
   int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
-                     std::unique_ptr<DataFrameSource> data_source) override;
+                     std::unique_ptr<DataFrameSource> data_source,
+                     bool end_stream) override;
 
   int SubmitTrailer(Http2StreamId stream_id,
                     absl::Span<const Header> trailers) override;
diff --git a/quiche/http2/adapter/nghttp2_adapter_test.cc b/quiche/http2/adapter/nghttp2_adapter_test.cc
index 5b07a48..eba07d5 100644
--- a/quiche/http2/adapter/nghttp2_adapter_test.cc
+++ b/quiche/http2/adapter/nghttp2_adapter_test.cc
@@ -127,17 +127,18 @@
 
   const char* kSentinel1 = "arbitrary pointer 1";
   const char* kSentinel3 = "arbitrary pointer 3";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id2;
 
-  const int32_t stream_id3 =
-      adapter->SubmitRequest(headers3, nullptr, const_cast<char*>(kSentinel3));
+  const int32_t stream_id3 = adapter->SubmitRequest(
+      headers3, nullptr, true, const_cast<char*>(kSentinel3));
   ASSERT_GT(stream_id3, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id3;
 
@@ -301,7 +302,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 0, 4, 0x0));
   EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 0, 4, 0x0, 0));
@@ -329,7 +331,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id1 = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
@@ -385,7 +388,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
-  const int32_t stream_id2 = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
@@ -407,7 +411,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -470,7 +475,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -530,7 +536,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -599,7 +606,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -608,7 +616,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -688,7 +697,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -749,7 +759,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
@@ -804,8 +815,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -886,7 +897,7 @@
   // before trailers are enqueued.
 
   const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
+      adapter->SubmitRequest(headers1, std::move(body1), false, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x4));
@@ -928,8 +939,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1007,7 +1018,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
@@ -1068,8 +1080,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1147,7 +1159,8 @@
       {"x-like-them-with-a-mouse", "no"},
   });
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -1187,8 +1200,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1273,8 +1286,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1348,8 +1361,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1416,8 +1429,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1483,8 +1496,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1561,7 +1574,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -1570,7 +1584,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -1640,7 +1655,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -1716,7 +1732,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -1802,7 +1819,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -1811,7 +1829,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   // The second request should be pending because of
@@ -1866,7 +1885,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/three"}});
 
-  const int32_t stream_id3 = adapter->SubmitRequest(headers3, nullptr, nullptr);
+  const int32_t stream_id3 =
+      adapter->SubmitRequest(headers3, nullptr, true, nullptr);
   ASSERT_GT(stream_id3, stream_id2);
 
   // Nghttp2 closes the pending stream on the next write attempt.
@@ -1892,8 +1912,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1963,7 +1983,8 @@
                  {":path", "/this/is/request/one"},
                  {"upgrade", "new-protocol"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
@@ -2060,12 +2081,12 @@
   auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
   body1->AppendPayload(kBody);
   body1->EndData();
-  int stream_id =
-      adapter->SubmitRequest(ToHeaders({{":method", "POST"},
-                                        {":scheme", "http"},
-                                        {":authority", "example.com"},
-                                        {":path", "/this/is/request/one"}}),
-                             std::move(body1), const_cast<char*>(kSentinel));
+  int stream_id = adapter->SubmitRequest(
+      ToHeaders({{":method", "POST"},
+                 {":scheme", "http"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}}),
+      std::move(body1), false, const_cast<char*>(kSentinel));
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2103,7 +2124,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             nullptr, nullptr);
+                             nullptr, true, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
   const char* kSentinel2 = "arbitrary pointer 2";
@@ -2176,7 +2197,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(frame_source), nullptr);
+                             std::move(frame_source), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2215,7 +2236,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(frame_source), nullptr);
+                             std::move(frame_source), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2273,7 +2294,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(frame_source), nullptr);
+                             std::move(frame_source), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2330,7 +2351,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(frame_source), nullptr);
+                             std::move(frame_source), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2396,7 +2417,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             nullptr, nullptr);
+                             nullptr, true, nullptr);
   EXPECT_GT(stream_id, 0);
 
   EXPECT_TRUE(adapter->want_write());
@@ -2479,14 +2500,14 @@
                  {":path", "/example/request"}});
   std::vector<int32_t> stream_ids;
   // Start two, which hits the limit.
-  int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  int32_t stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
   // Start two more, which must be queued.
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
@@ -2509,7 +2530,7 @@
 
   adapter->ProcessBytes(update_streams);
 
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
@@ -2534,7 +2555,8 @@
                                                  {":scheme", "http"},
                                                  {":authority", "example.com"},
                                                  {":path", "/"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   testing::InSequence s;
 
@@ -2664,7 +2686,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
       {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
@@ -2724,7 +2747,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
       {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
@@ -2775,7 +2799,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(
       ToHeaders({{"more-than-one-frame", std::string(20000, 'a')}})));
@@ -2829,7 +2854,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(
       ToHeaders({{"more-than-one-frame", std::string(20000, 'a')}})));
@@ -2911,7 +2937,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(body1), nullptr);
+                             std::move(body1), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2933,7 +2959,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/two"}}),
-                             nullptr, nullptr);
+                             nullptr, true, nullptr);
 
   // A new pending stream is created, but because of MAX_CONCURRENT_STREAMS, the
   // session should not want to write it at the moment.
@@ -3027,7 +3053,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(body1), nullptr);
+                             std::move(body1), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -3080,7 +3106,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(body1), nullptr);
+                             std::move(body1), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -3174,7 +3200,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
@@ -3263,7 +3290,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
@@ -3335,7 +3363,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
@@ -3400,12 +3429,12 @@
 
   const uint32_t large_frame_size = kDefaultFramePayloadSizeLimit + 42;
   adapter->SubmitSettings({{MAX_FRAME_SIZE, large_frame_size}});
-  const int32_t stream_id =
-      adapter->SubmitRequest(ToHeaders({{":method", "GET"},
-                                        {":scheme", "https"},
-                                        {":authority", "example.com"},
-                                        {":path", "/this/is/request/one"}}),
-                             /*data_source=*/nullptr, /*user_data=*/nullptr);
+  const int32_t stream_id = adapter->SubmitRequest(
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "https"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}}),
+      /*data_source=*/nullptr, true, /*user_data=*/nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -3467,12 +3496,12 @@
 
   const uint32_t large_frame_size = kDefaultFramePayloadSizeLimit + 42;
   adapter->SubmitSettings({{MAX_FRAME_SIZE, large_frame_size}});
-  const int32_t stream_id =
-      adapter->SubmitRequest(ToHeaders({{":method", "GET"},
-                                        {":scheme", "https"},
-                                        {":authority", "example.com"},
-                                        {":path", "/this/is/request/one"}}),
-                             /*data_source=*/nullptr, /*user_data=*/nullptr);
+  const int32_t stream_id = adapter->SubmitRequest(
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "https"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}}),
+      /*data_source=*/nullptr, true, /*user_data=*/nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -3680,7 +3709,7 @@
   body->AppendPayload("Here is some data, which will lead to a fatal error");
   TestDataFrameSource* body_ptr = body.get();
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_TRUE(adapter->want_write());
@@ -4114,7 +4143,7 @@
   auto* body1_ptr = body1.get();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -4200,7 +4229,7 @@
   body->EndData();
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(submit_result, 0);
 
   const std::vector<Header> trailers =
@@ -4269,7 +4298,7 @@
   TestDataFrameSource& body_ref = *body;
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(submit_result, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, ACK_FLAG));
@@ -5180,7 +5209,7 @@
   // with a lower last-stream-ID field, as the stream was client-initiated.
   const int submit_result =
       adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}),
-                              /*data_source=*/nullptr);
+                              /*data_source=*/nullptr, true);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_TRUE(adapter->want_write());
@@ -5261,7 +5290,7 @@
       1,
       ToHeaders({{":status", "404"},
                  {"x-comment", "I have no idea what you're talking about."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5343,7 +5372,7 @@
       1,
       ToHeaders({{":status", "404"},
                  {"x-comment", "I have no idea what you're talking about."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5469,7 +5498,7 @@
   body1->EndData();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5642,7 +5671,8 @@
   body1->AppendPayload("perfection");
   body1->EndData();
 
-  int submit_result = adapter->SubmitResponse(1, headers1, std::move(body1));
+  int submit_result =
+      adapter->SubmitResponse(1, headers1, std::move(body1), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
@@ -5699,7 +5729,8 @@
   auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
   TestDataFrameSource* body1_ptr = body1.get();
 
-  int submit_result = adapter->SubmitResponse(1, headers1, std::move(body1));
+  int submit_result =
+      adapter->SubmitResponse(1, headers1, std::move(body1), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
@@ -5777,7 +5808,7 @@
   body1->SimulateError();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5839,8 +5870,8 @@
   const int64_t result = adapter->ProcessBytes(frames);
   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
 
-  int submit_result =
-      adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
+  int submit_result = adapter->SubmitResponse(
+      1, ToHeaders({{":status", "200"}}), nullptr, true);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5886,8 +5917,8 @@
   const int64_t result = adapter->ProcessBytes(frames);
   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
 
-  int submit_result =
-      adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
+  int submit_result = adapter->SubmitResponse(
+      1, ToHeaders({{":status", "200"}}), nullptr, true);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -6012,7 +6043,7 @@
   body1->EndData();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -6125,7 +6156,7 @@
                  {"accept", "text/html"}});
 
   const int32_t stream_id1 =
-      client_adapter->SubmitRequest(headers1, nullptr, nullptr);
+      client_adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(client_visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -6178,7 +6209,7 @@
                  {"cookie", "d=e, f, g; h"}});
 
   const int32_t stream_id1 =
-      client_adapter->SubmitRequest(headers1, nullptr, nullptr);
+      client_adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(client_visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -6859,7 +6890,7 @@
   body->AppendPayload("Here is some data, which will be completely ignored!");
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
@@ -6926,7 +6957,7 @@
   body->AppendPayload("Here is some data, which will be completely ignored!");
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
@@ -7075,7 +7106,7 @@
   auto body = std::make_unique<TestDataFrameSource>(visitor, true);
   body->AppendPayload("This data is doomed to never be written.");
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   // Submit a WINDOW_UPDATE frame.
@@ -7764,7 +7795,7 @@
   TestDataFrameSource& body_ref = *body;
   body_ref.AppendPayload(std::string(70000, 'a'));
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
diff --git a/quiche/http2/adapter/oghttp2_adapter.cc b/quiche/http2/adapter/oghttp2_adapter.cc
index fbfc76a..907026e 100644
--- a/quiche/http2/adapter/oghttp2_adapter.cc
+++ b/quiche/http2/adapter/oghttp2_adapter.cc
@@ -132,13 +132,17 @@
 
 int32_t OgHttp2Adapter::SubmitRequest(
     absl::Span<const Header> headers,
-    std::unique_ptr<DataFrameSource> data_source, void* user_data) {
+    std::unique_ptr<DataFrameSource> data_source, bool end_stream,
+    void* user_data) {
+  QUICHE_DCHECK_EQ(end_stream, data_source == nullptr);
   return session_->SubmitRequest(headers, std::move(data_source), user_data);
 }
 
-int OgHttp2Adapter::SubmitResponse(
-    Http2StreamId stream_id, absl::Span<const Header> headers,
-    std::unique_ptr<DataFrameSource> data_source) {
+int OgHttp2Adapter::SubmitResponse(Http2StreamId stream_id,
+                                   absl::Span<const Header> headers,
+                                   std::unique_ptr<DataFrameSource> data_source,
+                                   bool end_stream) {
+  QUICHE_DCHECK_EQ(end_stream, data_source == nullptr);
   return session_->SubmitResponse(stream_id, headers, std::move(data_source));
 }
 
diff --git a/quiche/http2/adapter/oghttp2_adapter.h b/quiche/http2/adapter/oghttp2_adapter.h
index 76e3b93..3d00235 100644
--- a/quiche/http2/adapter/oghttp2_adapter.h
+++ b/quiche/http2/adapter/oghttp2_adapter.h
@@ -54,9 +54,10 @@
   void SubmitRst(Http2StreamId stream_id, Http2ErrorCode error_code) override;
   int32_t SubmitRequest(absl::Span<const Header> headers,
                         std::unique_ptr<DataFrameSource> data_source,
-                        void* user_data) override;
+                        bool end_stream, void* user_data) override;
   int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
-                     std::unique_ptr<DataFrameSource> data_source) override;
+                     std::unique_ptr<DataFrameSource> data_source,
+                     bool end_stream) override;
 
   int SubmitTrailer(Http2StreamId stream_id,
                     absl::Span<const Header> trailers) override;
diff --git a/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc b/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc
index d131daf..2a37ffc 100644
--- a/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc
+++ b/quiche/http2/adapter/oghttp2_adapter_metadata_test.cc
@@ -54,8 +54,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -140,7 +140,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -207,7 +208,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -284,7 +286,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -368,7 +371,7 @@
   body1->EndData();
 
   const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
+      adapter->SubmitRequest(headers1, std::move(body1), false, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -582,7 +585,7 @@
   body1->EndData();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
diff --git a/quiche/http2/adapter/oghttp2_adapter_test.cc b/quiche/http2/adapter/oghttp2_adapter_test.cc
index c83c67c..6ce1329 100644
--- a/quiche/http2/adapter/oghttp2_adapter_test.cc
+++ b/quiche/http2/adapter/oghttp2_adapter_test.cc
@@ -604,10 +604,14 @@
                                                  {":authority", "example.com"},
                                                  {":path", "/"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers, nullptr, nullptr);
-  const int32_t stream_id2 = adapter->SubmitRequest(headers, nullptr, nullptr);
-  const int32_t stream_id3 = adapter->SubmitRequest(headers, nullptr, nullptr);
-  const int32_t stream_id4 = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
+  const int32_t stream_id3 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
+  const int32_t stream_id4 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
@@ -686,7 +690,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -768,7 +773,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
@@ -802,7 +808,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id1 = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
@@ -867,7 +874,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
-  const int32_t stream_id2 = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _,
                                          END_STREAM_FLAG | END_HEADERS_FLAG));
@@ -893,7 +901,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -962,7 +971,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1028,7 +1038,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1098,7 +1109,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -1107,7 +1119,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1191,7 +1204,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1258,7 +1272,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1319,8 +1334,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1407,7 +1422,7 @@
   body1->EndData();
 
   const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
+      adapter->SubmitRequest(headers1, std::move(body1), false, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1456,8 +1471,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1538,8 +1553,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1614,8 +1629,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1689,8 +1704,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -1765,7 +1780,8 @@
       {"x-like-them-with-a-mouse", "no"},
   });
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1853,7 +1869,8 @@
       {":path", "/this/is/request/one"},
   });
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -1928,7 +1945,8 @@
       {":path", "/this/is/request/two"},
   });
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _,
@@ -1993,8 +2011,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -2101,7 +2119,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -2110,7 +2129,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -2187,7 +2207,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -2271,7 +2292,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -2367,7 +2389,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -2376,7 +2399,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/two"}});
 
-  const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
+  const int32_t stream_id2 =
+      adapter->SubmitRequest(headers2, nullptr, true, nullptr);
   ASSERT_GT(stream_id2, stream_id1);
 
   // The second request should be pending because of
@@ -2433,7 +2457,8 @@
                  {":authority", "example.com"},
                  {":path", "/this/is/request/three"}});
 
-  const int32_t stream_id3 = adapter->SubmitRequest(headers3, nullptr, nullptr);
+  const int32_t stream_id3 =
+      adapter->SubmitRequest(headers3, nullptr, true, nullptr);
   ASSERT_GT(stream_id3, stream_id2);
 
   // We close the pending stream on the next write attempt.
@@ -2461,8 +2486,8 @@
                  {":path", "/this/is/request/one"}});
 
   const char* kSentinel1 = "arbitrary pointer 1";
-  const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+  const int32_t stream_id1 = adapter->SubmitRequest(
+      headers1, nullptr, true, const_cast<char*>(kSentinel1));
   ASSERT_GT(stream_id1, 0);
   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
 
@@ -2541,7 +2566,8 @@
                  {":path", "/this/is/request/one"},
                  {"upgrade", "new-protocol"}});
 
-  const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
+  const int32_t stream_id1 =
+      adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -2658,7 +2684,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(body1), nullptr);
+                             std::move(body1), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2680,7 +2706,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/two"}}),
-                             nullptr, nullptr);
+                             nullptr, true, nullptr);
 
   // A new pending stream is created, but because of MAX_CONCURRENT_STREAMS, the
   // session should not want to write it at the moment.
@@ -2781,7 +2807,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(body1), nullptr);
+                             std::move(body1), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2838,7 +2864,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             std::move(body1), nullptr);
+                             std::move(body1), false, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -2941,7 +2967,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -3033,12 +3060,12 @@
 
   const uint32_t large_frame_size = kDefaultFramePayloadSizeLimit + 42;
   adapter->SubmitSettings({{MAX_FRAME_SIZE, large_frame_size}});
-  const int32_t stream_id =
-      adapter->SubmitRequest(ToHeaders({{":method", "GET"},
-                                        {":scheme", "https"},
-                                        {":authority", "example.com"},
-                                        {":path", "/this/is/request/one"}}),
-                             /*data_source=*/nullptr, /*user_data=*/nullptr);
+  const int32_t stream_id = adapter->SubmitRequest(
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "https"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}}),
+      /*data_source=*/nullptr, true, /*user_data=*/nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -3106,12 +3133,12 @@
 
   const uint32_t large_frame_size = kDefaultFramePayloadSizeLimit + 42;
   adapter->SubmitSettings({{MAX_FRAME_SIZE, large_frame_size}});
-  const int32_t stream_id =
-      adapter->SubmitRequest(ToHeaders({{":method", "GET"},
-                                        {":scheme", "https"},
-                                        {":authority", "example.com"},
-                                        {":path", "/this/is/request/one"}}),
-                             /*data_source=*/nullptr, /*user_data=*/nullptr);
+  const int32_t stream_id = adapter->SubmitRequest(
+      ToHeaders({{":method", "GET"},
+                 {":scheme", "https"},
+                 {":authority", "example.com"},
+                 {":path", "/this/is/request/one"}}),
+      /*data_source=*/nullptr, true, /*user_data=*/nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -3197,7 +3224,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
                                          END_STREAM_FLAG | END_HEADERS_FLAG));
@@ -3273,7 +3301,8 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id, 0);
   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
                                          END_STREAM_FLAG | END_HEADERS_FLAG));
@@ -3368,7 +3397,7 @@
                                         {":scheme", "http"},
                                         {":authority", "example.com"},
                                         {":path", "/this/is/request/one"}}),
-                             nullptr, nullptr);
+                             nullptr, true, nullptr);
   EXPECT_GT(stream_id, 0);
 
   EXPECT_TRUE(adapter->want_write());
@@ -3439,7 +3468,7 @@
   body1->EndData();
 
   const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
+      adapter->SubmitRequest(headers1, std::move(body1), false, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -3453,7 +3482,7 @@
   body2->EndData();
 
   const int32_t stream_id2 =
-      adapter->SubmitRequest(headers2, std::move(body2), nullptr);
+      adapter->SubmitRequest(headers2, std::move(body2), false, nullptr);
   ASSERT_GT(stream_id2, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -3521,7 +3550,7 @@
   body1->EndData();
 
   const int32_t stream_id1 =
-      adapter->SubmitRequest(headers1, std::move(body1), nullptr);
+      adapter->SubmitRequest(headers1, std::move(body1), false, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   const std::vector<Header> headers2 =
@@ -3536,7 +3565,7 @@
   body2->EndData();
 
   const int32_t stream_id2 =
-      adapter->SubmitRequest(headers2, std::move(body2), nullptr);
+      adapter->SubmitRequest(headers2, std::move(body2), false, nullptr);
   ASSERT_GT(stream_id2, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -3604,14 +3633,14 @@
                  {":path", "/example/request"}});
   std::vector<int32_t> stream_ids;
   // Start two, which hits the limit.
-  int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  int32_t stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
   // Start two more, which must be queued.
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
@@ -3637,7 +3666,7 @@
   EXPECT_CALL(visitor, OnSettingsEnd());
 
   adapter->ProcessBytes(update_streams);
-  stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  stream_id = adapter->SubmitRequest(headers, nullptr, true, nullptr);
   stream_ids.push_back(stream_id);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
@@ -3670,7 +3699,8 @@
                                                  {":scheme", "http"},
                                                  {":authority", "example.com"},
                                                  {":path", "/"}});
-  const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
+  const int32_t stream_id =
+      adapter->SubmitRequest(headers, nullptr, true, nullptr);
 
   testing::InSequence s;
 
@@ -4198,7 +4228,7 @@
   body->AppendPayload("Here is some data, which will lead to a fatal error");
   TestDataFrameSource* body_ptr = body.get();
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_TRUE(adapter->want_write());
@@ -4311,7 +4341,8 @@
   body1->AppendPayload("perfection");
   body1->EndData();
 
-  int submit_result = adapter->SubmitResponse(1, headers1, std::move(body1));
+  int submit_result =
+      adapter->SubmitResponse(1, headers1, std::move(body1), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -4372,7 +4403,8 @@
   auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
   TestDataFrameSource* body1_ptr = body1.get();
 
-  int submit_result = adapter->SubmitResponse(1, headers1, std::move(body1));
+  int submit_result =
+      adapter->SubmitResponse(1, headers1, std::move(body1), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -4572,7 +4604,7 @@
   body1->SimulateError();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -4638,8 +4670,8 @@
   const int64_t result = adapter->ProcessBytes(frames);
   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
 
-  int submit_result =
-      adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
+  int submit_result = adapter->SubmitResponse(
+      1, ToHeaders({{":status", "200"}}), nullptr, true);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -4692,8 +4724,8 @@
   const int64_t result = adapter->ProcessBytes(frames);
   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
 
-  int submit_result =
-      adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
+  int submit_result = adapter->SubmitResponse(
+      1, ToHeaders({{":status", "200"}}), nullptr, true);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -4747,8 +4779,8 @@
   const int64_t result = adapter->ProcessBytes(frames);
   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
 
-  int submit_result =
-      adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
+  int submit_result = adapter->SubmitResponse(
+      1, ToHeaders({{":status", "200"}}), nullptr, true);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -4874,7 +4906,7 @@
   body1->EndData();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5186,7 +5218,7 @@
     auto* body1_ptr = body1.get();
     int submit_result = adapter->SubmitResponse(
         1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-        std::move(body1));
+        std::move(body1), false);
     EXPECT_EQ(submit_result, 0);
     EXPECT_TRUE(adapter->want_write());
 
@@ -5279,7 +5311,7 @@
   auto* body1_ptr = body1.get();
   int submit_result = adapter->SubmitResponse(
       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -5385,7 +5417,7 @@
   body->EndData();
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(submit_result, 0);
 
   const std::vector<Header> trailers =
@@ -5456,7 +5488,7 @@
   TestDataFrameSource& body_ref = *body;
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(submit_result, 0);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -6352,7 +6384,7 @@
   // with a lower last-stream-ID field, as the stream was client-initiated.
   const int submit_result =
       adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}),
-                              /*data_source=*/nullptr);
+                              /*data_source=*/nullptr, true);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_TRUE(adapter->want_write());
@@ -6443,7 +6475,7 @@
       1,
       ToHeaders({{":status", "404"},
                  {"x-comment", "I have no idea what you're talking about."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -6530,7 +6562,7 @@
       1,
       ToHeaders({{":status", "404"},
                  {"x-comment", "I have no idea what you're talking about."}}),
-      std::move(body1));
+      std::move(body1), false);
   EXPECT_EQ(submit_result, 0);
   EXPECT_TRUE(adapter->want_write());
 
@@ -6639,7 +6671,7 @@
   EXPECT_CALL(server_visitor, OnEndHeadersForStream(_))
       .WillRepeatedly([&server_adapter](Http2StreamId stream_id) {
         server_adapter->SubmitResponse(
-            stream_id, ToHeaders({{":status", "200"}}), nullptr);
+            stream_id, ToHeaders({{":status", "200"}}), nullptr, true);
         server_adapter->Send();
         return true;
       });
@@ -6660,7 +6692,7 @@
                          {":authority", "example.com"},
                          {":path",
                           absl::StrCat("/this/is/request/", new_stream_id)}}),
-              std::move(body), nullptr);
+              std::move(body), false, nullptr);
           EXPECT_EQ(new_stream_id, created_stream_id);
           client_adapter->Send();
         }
@@ -6673,7 +6705,7 @@
                  {":scheme", "http"},
                  {":authority", "example.com"},
                  {":path", "/this/is/request/one"}}),
-      nullptr, nullptr);
+      nullptr, true, nullptr);
   EXPECT_EQ(stream_id, 1);
 
   client_adapter->Send();
@@ -6695,7 +6727,7 @@
                  {"accept", "text/html"}});
 
   const int32_t stream_id1 =
-      client_adapter->SubmitRequest(headers1, nullptr, nullptr);
+      client_adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(client_visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -6756,7 +6788,7 @@
                  {"cookie", "d=e, f, g; h"}});
 
   const int32_t stream_id1 =
-      client_adapter->SubmitRequest(headers1, nullptr, nullptr);
+      client_adapter->SubmitRequest(headers1, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   EXPECT_CALL(client_visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -7357,7 +7389,7 @@
   body->AppendPayload("Here is some data, which will be completely ignored!");
 
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
@@ -7541,7 +7573,7 @@
   auto body = std::make_unique<TestDataFrameSource>(visitor, true);
   body->AppendPayload("This data is doomed to never be written.");
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   // Submit a WINDOW_UPDATE frame.
@@ -8419,7 +8451,7 @@
   TestDataFrameSource& body_ref = *body;
   body_ref.AppendPayload(std::string(70000, 'a'));
   int submit_result = adapter->SubmitResponse(
-      1, ToHeaders({{":status", "200"}}), std::move(body));
+      1, ToHeaders({{":status", "200"}}), std::move(body), false);
   ASSERT_EQ(0, submit_result);
 
   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
@@ -8489,7 +8521,7 @@
                  {":path", "/this/is/request/one"}});
 
   const int32_t stream_id1 =
-      client_adapter->SubmitRequest(request_headers, nullptr, nullptr);
+      client_adapter->SubmitRequest(request_headers, nullptr, true, nullptr);
   ASSERT_GT(stream_id1, 0);
 
   // Client visitor expectations on send.
@@ -8530,8 +8562,8 @@
                  {"set-cookie", "chocolate_chip=yummy"},
                  {"set-cookie", "macadamia_nut=okay"}});
 
-  EXPECT_EQ(
-      0, server_adapter->SubmitResponse(stream_id1, response_headers, nullptr));
+  EXPECT_EQ(0, server_adapter->SubmitResponse(stream_id1, response_headers,
+                                              nullptr, true));
 
   // Server visitor expectations on send.
   // Server preface with initial SETTINGS.