Improve handing of frames with empty payload in HttpDecoder.

The current draft allows HTTP frames to have an empty payload.  Before this CL, there were some issues with our implementation:

(1) Frames with empty payload were not processed until data from the next frame arrived.
(2) OnDataFrameStart() and OnHeadersFrameStart() were only called after some more data (frame payload or next frame) arrived, even though all necessary argument values were already available when the frame header was processed.
(3) If a DATA or HEADERS or PUSH_PROMISE frame had no payload, On*FramePayload() was called once with an empty string argument.

This CL adds one more state to the state machine, and fixes these issues.  It also documents that the |payload| argument of On*FramePayload() cannot be empty by adding some DCHECKs.

gfe-relnote: n/a.  Change in QUIC v99 only, code path not used in production.
PiperOrigin-RevId: 238811718
Change-Id: I020dd16ebdb529a77fb2fa7969a65ceede667530
diff --git a/quic/core/http/http_decoder.h b/quic/core/http/http_decoder.h
index cbfa65e..1cc973a 100644
--- a/quic/core/http/http_decoder.h
+++ b/quic/core/http/http_decoder.h
@@ -65,8 +65,9 @@
     // Called when a DATA frame has been received.
     // |frame_length| contains DATA frame length and payload length.
     virtual void OnDataFrameStart(Http3FrameLengths frame_length) = 0;
-    // Called when the payload of a DATA frame has read. May be called
-    // multiple times for a single frame.
+    // Called when part of the payload of a DATA frame has been read.  May be
+    // called multiple times for a single frame.  |payload| is guaranteed to be
+    // non-empty.
     virtual void OnDataFramePayload(QuicStringPiece payload) = 0;
     // Called when a DATA frame has been completely processed.
     virtual void OnDataFrameEnd() = 0;
@@ -74,8 +75,9 @@
     // Called when a HEADERS frame has been recevied.
     // |frame_length| contains HEADERS frame length and payload length.
     virtual void OnHeadersFrameStart(Http3FrameLengths frame_length) = 0;
-    // Called when the payload of a HEADERS frame has read. May be called
-    // multiple times for a single frame.
+    // Called when part of the payload of a HEADERS frame has been read.  May be
+    // called multiple times for a single frame.  |payload| is guaranteed to be
+    // non-empty.
     virtual void OnHeadersFramePayload(QuicStringPiece payload) = 0;
     // Called when a HEADERS frame has been completely processed.
     // |frame_len| is the length of the HEADERS frame payload.
@@ -83,8 +85,9 @@
 
     // Called when a PUSH_PROMISE frame has been recevied for |push_id|.
     virtual void OnPushPromiseFrameStart(PushId push_id) = 0;
-    // Called when the payload of a PUSH_PROMISE frame has read. May be called
-    // multiple times for a single frame.
+    // Called when part of the payload of a PUSH_PROMISE frame has been read.
+    // May be called multiple times for a single frame.  |payload| is guaranteed
+    // to be non-empty.
     virtual void OnPushPromiseFramePayload(QuicStringPiece payload) = 0;
     // Called when a PUSH_PROMISE frame has been completely processed.
     virtual void OnPushPromiseFrameEnd() = 0;
@@ -118,6 +121,7 @@
     STATE_READING_FRAME_LENGTH,
     STATE_READING_FRAME_TYPE,
     STATE_READING_FRAME_PAYLOAD,
+    STATE_FINISH_PARSING,
     STATE_ERROR
   };
 
@@ -126,13 +130,18 @@
   void ReadFrameLength(QuicDataReader* reader);
 
   // Reads the type of a frame from |reader|. Sets error_ and error_detail_
-  // if there are any errors.
+  // if there are any errors.  Also calls OnDataFrameStart() or
+  // OnHeadersFrameStart() for appropriate frame types.
   void ReadFrameType(QuicDataReader* reader);
 
   // Reads the payload of the current frame from |reader| and processes it,
   // possibly buffering the data or invoking the visitor.
   void ReadFramePayload(QuicDataReader* reader);
 
+  // Optionally parses buffered data; calls visitor method to signal that frame
+  // had been parsed completely.
+  void FinishParsing();
+
   // Discards any remaining frame payload from |reader|.
   void DiscardFramePayload(QuicDataReader* reader);