Fix QPACK crash by unregistering observers with QpackHeaderTable.

QpackHeaderTable is owned by QpackDecoder, owned by QuicSpdySession.  Each
observer is a QpackProgressiveDecoder, owned by QpackHeaderAccumulator, owned by
QuicSpdyStream.  If a stream is deleted (local cancellation, reset received from
peer), then the observer must be deregistered with QpackHeaderTable in order to
avoid a crash.

gfe-relnote: n/a, change to QUIC v99-only code.  Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 272562981
Change-Id: Ia49f2ef9aeeebcccb83405107f0224ee7d23694f
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc
index 30f15a5..7274ce4 100644
--- a/quic/core/qpack/qpack_header_table.cc
+++ b/quic/core/qpack/qpack_header_table.cc
@@ -197,6 +197,21 @@
   observers_.insert({required_insert_count, observer});
 }
 
+void QpackHeaderTable::UnregisterObserver(uint64_t required_insert_count,
+                                          Observer* observer) {
+  auto it = observers_.lower_bound(required_insert_count);
+  while (it != observers_.end() && it->first == required_insert_count) {
+    if (it->second == observer) {
+      observers_.erase(it);
+      return;
+    }
+    ++it;
+  }
+
+  // |observer| must have been registered.
+  QUIC_NOTREACHED();
+}
+
 uint64_t QpackHeaderTable::draining_index(float draining_fraction) const {
   DCHECK_LE(0.0, draining_fraction);
   DCHECK_LE(draining_fraction, 1.0);