Set max_outbound_header_list_size_ when receiving SETTINGS_MAX_HEADER_LIST_SIZE.

Also change max_outbound_header_list_size_ default value to numeric_limits::max,
because the default value of this setting is unlimited both in Google QUIC [1]
and in IETF QUIC [2].

[1] https://httpwg.org/specs/rfc7540.html#SettingValues
[2] https://quicwg.org/base-drafts/draft-ietf-quic-http.html#name-defined-settings-parameters

gfe-relnote: n/a (max_outbound_header_list_size_ is never used in production)
PiperOrigin-RevId: 293124322
Change-Id: I12f4bceef90030905b7c294724936ec9e7c6dd1e
diff --git a/quic/core/http/quic_headers_stream_test.cc b/quic/core/http/quic_headers_stream_test.cc
index 35c74fc..aef31b1 100644
--- a/quic/core/http/quic_headers_stream_test.cc
+++ b/quic/core/http/quic_headers_stream_test.cc
@@ -646,7 +646,7 @@
   stream_frame_.data_length = frame.size();
   headers_stream_->OnStreamFrame(stream_frame_);
   EXPECT_EQ(kTestHeaderTableSize, QuicSpdySessionPeer::GetSpdyFramer(&session_)
-                                      .header_encoder_table_size());
+                                      ->header_encoder_table_size());
 }
 
 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
diff --git a/quic/core/http/quic_receive_control_stream_test.cc b/quic/core/http/quic_receive_control_stream_test.cc
index 489d983..84cc8ed 100644
--- a/quic/core/http/quic_receive_control_stream_test.cc
+++ b/quic/core/http/quic_receive_control_stream_test.cc
@@ -5,9 +5,11 @@
 #include "net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h"
 
 #include "net/third_party/quiche/src/quic/core/http/http_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.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_ptr_util.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -15,6 +17,9 @@
 #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
 
 namespace quic {
+
+class QpackEncoder;
+
 namespace test {
 
 namespace {
@@ -150,11 +155,24 @@
   SettingsFrame settings;
   settings.values[3] = 2;
   settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
+  settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 12;
+  settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 37;
   std::string data = EncodeSettings(settings);
   QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
-  EXPECT_NE(5u, session_.max_outbound_header_list_size());
+
+  QpackEncoder* qpack_encoder = session_.qpack_encoder();
+  QpackHeaderTable* header_table =
+      QpackEncoderPeer::header_table(qpack_encoder);
+  EXPECT_EQ(std::numeric_limits<size_t>::max(),
+            session_.max_outbound_header_list_size());
+  EXPECT_EQ(0u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+  EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
+
   receive_control_stream_->OnStreamFrame(frame);
+
   EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+  EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+  EXPECT_EQ(37u, header_table->maximum_dynamic_table_capacity());
 }
 
 // Regression test for https://crbug.com/982648.
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index 25b1b0a..8215078 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <cstdint>
+#include <limits>
 #include <string>
 #include <utility>
 
@@ -338,7 +339,7 @@
           kDefaultQpackMaxDynamicTableCapacity),
       qpack_maximum_blocked_streams_(kDefaultMaximumBlockedStreams),
       max_inbound_header_list_size_(kDefaultMaxUncompressedHeaderSize),
-      max_outbound_header_list_size_(kDefaultMaxUncompressedHeaderSize),
+      max_outbound_header_list_size_(std::numeric_limits<size_t>::max()),
       server_push_enabled_(true),
       stream_id_(
           QuicUtils::GetInvalidStreamId(connection->transport_version())),
@@ -854,12 +855,11 @@
         }
       }
       break;
-    // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
-    // clients are actually sending it.
     case spdy::SETTINGS_MAX_HEADER_LIST_SIZE:
       QUIC_DVLOG(1) << ENDPOINT
                     << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
                     << value;
+      max_outbound_header_list_size_ = value;
       break;
     default:
       QUIC_DLOG(ERROR) << ENDPOINT << "Unknown setting identifier " << id
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h
index c9bfb27..95f90c9 100644
--- a/quic/core/http/quic_spdy_session.h
+++ b/quic/core/http/quic_spdy_session.h
@@ -417,7 +417,7 @@
 
   // The maximum size of a header block that can be sent to the peer. This field
   // is informed and set by the peer via SETTINGS frame.
-  // TODO(renjietang): Honor this field when sending headers.
+  // TODO(b/148616439): Honor this field when sending headers.
   size_t max_outbound_header_list_size_;
 
   // Set during handshake. If true, resources in x-associated-content and link
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 6ce22a9..82ac0d1 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -5,6 +5,7 @@
 #include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
 
 #include <cstdint>
+#include <limits>
 #include <set>
 #include <string>
 #include <utility>
@@ -14,6 +15,7 @@
 #include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
 #include "net/third_party/quiche/src/quic/core/http/http_constants.h"
 #include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
 #include "net/third_party/quiche/src/quic/core/quic_config.h"
 #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
 #include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
@@ -2706,6 +2708,43 @@
   session_.OnHttp3GoAway(stream_id);
 }
 
+TEST_P(QuicSpdySessionTestServer, OnSetting) {
+  if (VersionUsesHttp3(transport_version())) {
+    EXPECT_EQ(std::numeric_limits<size_t>::max(),
+              session_.max_outbound_header_list_size());
+    session_.OnSetting(SETTINGS_MAX_HEADER_LIST_SIZE, 5);
+    EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+
+    QpackEncoder* qpack_encoder = session_.qpack_encoder();
+    EXPECT_EQ(0u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+    session_.OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 12);
+    EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+
+    QpackHeaderTable* header_table =
+        QpackEncoderPeer::header_table(qpack_encoder);
+    EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
+    session_.OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 37);
+    EXPECT_EQ(37u, header_table->maximum_dynamic_table_capacity());
+
+    return;
+  }
+
+  EXPECT_EQ(std::numeric_limits<size_t>::max(),
+            session_.max_outbound_header_list_size());
+  session_.OnSetting(SETTINGS_MAX_HEADER_LIST_SIZE, 5);
+  EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+
+  EXPECT_TRUE(session_.server_push_enabled());
+  session_.OnSetting(spdy::SETTINGS_ENABLE_PUSH, 0);
+  EXPECT_FALSE(session_.server_push_enabled());
+
+  spdy::HpackEncoder* hpack_encoder =
+      QuicSpdySessionPeer::GetSpdyFramer(&session_)->GetHpackEncoder();
+  EXPECT_EQ(4096u, hpack_encoder->CurrentHeaderTableSizeSetting());
+  session_.OnSetting(spdy::SETTINGS_HEADER_TABLE_SIZE, 59);
+  EXPECT_EQ(59u, hpack_encoder->CurrentHeaderTableSizeSetting());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/test_tools/quic_spdy_session_peer.cc b/quic/test_tools/quic_spdy_session_peer.cc
index cad9599..4730ef9 100644
--- a/quic/test_tools/quic_spdy_session_peer.cc
+++ b/quic/test_tools/quic_spdy_session_peer.cc
@@ -32,9 +32,8 @@
 }
 
 // static
-const spdy::SpdyFramer& QuicSpdySessionPeer::GetSpdyFramer(
-    QuicSpdySession* session) {
-  return session->spdy_framer_;
+spdy::SpdyFramer* QuicSpdySessionPeer::GetSpdyFramer(QuicSpdySession* session) {
+  return &session->spdy_framer_;
 }
 
 void QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
diff --git a/quic/test_tools/quic_spdy_session_peer.h b/quic/test_tools/quic_spdy_session_peer.h
index 1cfd45f..87eda44 100644
--- a/quic/test_tools/quic_spdy_session_peer.h
+++ b/quic/test_tools/quic_spdy_session_peer.h
@@ -28,7 +28,7 @@
   static QuicHeadersStream* GetHeadersStream(QuicSpdySession* session);
   static void SetHeadersStream(QuicSpdySession* session,
                                QuicHeadersStream* headers_stream);
-  static const spdy::SpdyFramer& GetSpdyFramer(QuicSpdySession* session);
+  static spdy::SpdyFramer* GetSpdyFramer(QuicSpdySession* session);
   static void SetHpackEncoderDebugVisitor(
       QuicSpdySession* session,
       std::unique_ptr<QuicHpackDebugVisitor> visitor);