Do not pretend receiving FIN when receiving trailers in QUIC v99.

In Google QUIC, trailing HEADERS must have FIN bit.  In IETF QUIC, HTTP/3 frames
do not have flags, so trailing HEADERS will never have FIN.  This CL makes
QuicSpdyStream stop faking a FIN bit.

In non-v99 QUIC, |fin| must be true at the end of OnTrailingHeadersComplete(),
otherwise the connection would have been closed in line 568.

In v99 QUIC, |fin| is false in production, when OnStreamHeaderList() is called
from OnHeadersFrameEnd().  However, a large number of tests call
OnStreamHeaderList() with fin = true, so this needs to be supported for the time
being.  See linked bug.

This is prework for https://crbug.com/978733.  I do not want QuicSpdyStream to
close the connection when trailers arrive, so that it can signal an error if
other frames are received afterwards.

Also, according to
https://quicwg.org/base-drafts/draft-ietf-quic-http.html#request-response,
PUSH_PROMISE frames can arrive after trailers, so the stream really should
remain open.

This CL also fixes descriptions of some QuicSpdyStream methods related to FIN
flag.

gfe-relnote: n/a, QUIC v99-only change.
PiperOrigin-RevId: 255681867
Change-Id: I33928191e35d601514a0be5b18b8aa5ff389c831
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index f02eaeb..e3d9357 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -589,12 +589,13 @@
     return;
   }
   trailers_decompressed_ = true;
-  const QuicStreamOffset offset =
-      VersionUsesQpack(spdy_session_->connection()->transport_version())
-          ? flow_controller()->highest_received_byte_offset()
-          : final_byte_offset;
-  OnStreamFrame(
-      QuicStreamFrame(id(), /* fin = */ true, offset, QuicStringPiece()));
+  if (fin) {
+    const QuicStreamOffset offset =
+        VersionUsesQpack(transport_version())
+            ? flow_controller()->highest_received_byte_offset()
+            : final_byte_offset;
+    OnStreamFrame(QuicStreamFrame(id(), fin, offset, QuicStringPiece()));
+  }
 }
 
 void QuicSpdyStream::OnPriorityFrame(SpdyPriority priority) {
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h
index b6b46fe..1a5c1b6 100644
--- a/quic/core/http/quic_spdy_stream.h
+++ b/quic/core/http/quic_spdy_stream.h
@@ -168,7 +168,8 @@
   static bool ParseHeaderStatusCode(const spdy::SpdyHeaderBlock& header,
                                     int* status_code);
 
-  // Returns true when all data has been read from the peer, including the fin.
+  // Returns true when all data from the peer has been read and consumed,
+  // including the fin.
   bool IsDoneReading() const;
   bool HasBytesToRead() const;
 
@@ -191,8 +192,8 @@
   // Returns true if headers have been fully read and consumed.
   bool FinishedReadingHeaders() const;
 
-  // Returns true if trailers have been fully read and consumed, or FIN has
-  // been received and there are no trailers.
+  // Returns true if FIN has been received and either trailers have been fully
+  // read and consumed or there are no trailers.
   bool FinishedReadingTrailers() const;
 
   // Called when owning session is getting deleted to avoid subsequent
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index 2cb4bce..bab9228 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -1752,7 +1752,7 @@
   EXPECT_TRUE(stream_->trailers_decompressed());
   EXPECT_EQ(trailers_block, stream_->received_trailers());
 
-  EXPECT_FALSE(stream_->IsDoneReading());
+  EXPECT_TRUE(stream_->HasBytesToRead());
 
   // Consume data.
   char buffer[2048];
@@ -1762,7 +1762,7 @@
   size_t bytes_read = stream_->Readv(&vec, 1);
   EXPECT_EQ(kDataFramePayload, QuicStringPiece(buffer, bytes_read));
 
-  EXPECT_TRUE(stream_->IsDoneReading());
+  EXPECT_FALSE(stream_->HasBytesToRead());
 }
 
 // The test stream will receive a stream frame containing malformed headers and