Consolidate set_allow_fin() calls in MoqtBidiStreamBase.

All bidi streams can be FINed, and some overloads were missing.

This is an oversight caught in Oct 2026 interop.

PiperOrigin-RevId: 998723491
diff --git a/quiche/quic/moqt/moqt_bidi_stream.h b/quiche/quic/moqt/moqt_bidi_stream.h
index 305c0d1..35bb5cd 100644
--- a/quiche/quic/moqt/moqt_bidi_stream.h
+++ b/quiche/quic/moqt/moqt_bidi_stream.h
@@ -60,6 +60,7 @@
   void BindStream(MoqtStreamTypeParser parser) {
     QUICHE_DCHECK(!stream_parser_.has_value());
     stream_parser_.emplace(std::move(parser));
+    stream_parser_->set_allow_fin(true);
     outgoing_message_queue_.SetStream(stream_parser_->stream());
     OnStreamBound();
   }
@@ -67,6 +68,7 @@
   void BindStream(webtransport::Stream* absl_nonnull stream) {
     QUICHE_DCHECK(!stream_parser_.has_value());
     stream_parser_.emplace(stream);
+    stream_parser_->set_allow_fin(true);
     outgoing_message_queue_.SetStream(stream);
     OnStreamBound();
   }
diff --git a/quiche/quic/moqt/moqt_bidi_stream_test.cc b/quiche/quic/moqt/moqt_bidi_stream_test.cc
index 6ec932c..1663c03 100644
--- a/quiche/quic/moqt/moqt_bidi_stream_test.cc
+++ b/quiche/quic/moqt/moqt_bidi_stream_test.cc
@@ -103,6 +103,26 @@
   EXPECT_TRUE(stream_->detached_);
 }
 
+TEST_F(MoqtBidiStreamTest, ReceiveFin) {
+  webtransport::test::InMemoryStream stream(0);
+  stream_->BindStream(&stream);
+  MoqtFramer framer(/*using_webtrans=*/true, quic::Perspective::IS_SERVER);
+  stream.Receive(framer.SerializeObjectAck(MoqtObjectAck()).AsStringView(),
+                 /*fin=*/true);
+  stream_->OnCanRead();
+}
+
+TEST_F(MoqtBidiStreamTest, ReceiveFinWithTypeParser) {
+  webtransport::test::InMemoryStream stream(0);
+  MoqtFramer framer(/*using_webtrans=*/true, quic::Perspective::IS_SERVER);
+  stream.Receive(framer.SerializeObjectAck(MoqtObjectAck()).AsStringView(),
+                 /*fin=*/true);
+  MoqtStreamTypeParser parser(&stream);
+  QUICHE_ASSERT_OK(parser.ReadStreamType().status());
+  stream_->BindStream(std::move(parser));
+  stream_->OnCanRead();
+}
+
 TEST_F(MoqtBidiStreamTest, IncomingStopSending) {
   stream_->BindStream(&mock_stream_);
   EXPECT_CALL(mock_stream_, SendStopSending(1234));
diff --git a/quiche/quic/moqt/moqt_fetch_stream.cc b/quiche/quic/moqt/moqt_fetch_stream.cc
index 681ce07..cc4ac4b 100644
--- a/quiche/quic/moqt/moqt_fetch_stream.cc
+++ b/quiche/quic/moqt/moqt_fetch_stream.cc
@@ -118,7 +118,6 @@
 }
 
 void MoqtFetchRequestStream::OnStreamBound() {
-  stream_parser()->set_allow_fin(true);
   // TODO(martinduke): Set the priority for this stream.
   MoqtFetch fetch;
   fetch.request_id = request_id();
diff --git a/quiche/quic/moqt/moqt_fetch_stream.h b/quiche/quic/moqt/moqt_fetch_stream.h
index 57d4604..dbf479f 100644
--- a/quiche/quic/moqt/moqt_fetch_stream.h
+++ b/quiche/quic/moqt/moqt_fetch_stream.h
@@ -120,7 +120,7 @@
 
   // MoqtBidiStreamBase overrides.
   using MoqtBidiStreamBase::OnControlMessage;
-  void OnStreamBound() override { stream_parser()->set_allow_fin(true); }
+  void OnStreamBound() override {}
   absl::Status OnRawControlMessage(
       const MoqtRawControlMessage& message) override;
   absl::Status OnControlMessage(const MoqtFetch& message);
diff --git a/quiche/quic/moqt/moqt_publish_namespace_stream.cc b/quiche/quic/moqt/moqt_publish_namespace_stream.cc
index 1896d31..dc6c716 100644
--- a/quiche/quic/moqt/moqt_publish_namespace_stream.cc
+++ b/quiche/quic/moqt/moqt_publish_namespace_stream.cc
@@ -24,7 +24,6 @@
   MoqtPublishNamespace message{request_id_, prefix_, parameters_};
   SendOrBufferMessageOrFatal(framer()->SerializePublishNamespace(message),
                              false);
-  stream_parser()->set_allow_fin(true);
   QUIC_DLOG(INFO) << "Sent PUBLISH_NAMESPACE message for " << prefix_;
 }
 
diff --git a/quiche/quic/moqt/moqt_publish_stream.cc b/quiche/quic/moqt/moqt_publish_stream.cc
index 5c1d0d0..4d8987a 100644
--- a/quiche/quic/moqt/moqt_publish_stream.cc
+++ b/quiche/quic/moqt/moqt_publish_stream.cc
@@ -49,7 +49,6 @@
 }
 
 void MoqtPublishRequestStream::OnStreamBound() {
-  stream_parser()->set_allow_fin(true);
   publisher_->parameters().largest_object =
       publisher_->publisher().largest_location();
   publisher_->parameters().expires = publisher_->publisher().expiration();
diff --git a/quiche/quic/moqt/moqt_publish_stream.h b/quiche/quic/moqt/moqt_publish_stream.h
index c2c1205..b03101e 100644
--- a/quiche/quic/moqt/moqt_publish_stream.h
+++ b/quiche/quic/moqt/moqt_publish_stream.h
@@ -96,7 +96,6 @@
   // MoqtBidiStreamBase overrides.
   using MoqtBidiStreamBase::OnControlMessage;
   void OnStreamBound() override {
-    stream_parser()->set_allow_fin(true);
     // TODO(martinduke): Set the priority for this stream.
   }
   absl::Status OnRawControlMessage(
diff --git a/quiche/quic/moqt/moqt_subscribe_stream.cc b/quiche/quic/moqt/moqt_subscribe_stream.cc
index e4713f8..193f173 100644
--- a/quiche/quic/moqt/moqt_subscribe_stream.cc
+++ b/quiche/quic/moqt/moqt_subscribe_stream.cc
@@ -49,7 +49,6 @@
       alarm_factory_(alarm_factory) {}
 
 void MoqtSubscribeRequestStream::OnStreamBound() {
-  stream_parser()->set_allow_fin(true);
   MoqtSubscribe subscribe{track_->request_id(), track_->full_track_name(),
                           track_->const_parameters()};
   SendOrBufferMessageOrFatal(framer()->SerializeSubscribe(subscribe));
diff --git a/quiche/quic/moqt/moqt_subscribe_stream.h b/quiche/quic/moqt/moqt_subscribe_stream.h
index cd96872..48041ea 100644
--- a/quiche/quic/moqt/moqt_subscribe_stream.h
+++ b/quiche/quic/moqt/moqt_subscribe_stream.h
@@ -79,7 +79,7 @@
 
   // MoqtBidiStreamBase overrides.
   using MoqtBidiStreamBase::OnControlMessage;
-  void OnStreamBound() override { stream_parser()->set_allow_fin(true); }
+  void OnStreamBound() override {}
   absl::Status OnRawControlMessage(
       const MoqtRawControlMessage& message) override;
 
diff --git a/quiche/quic/moqt/moqt_track_status_stream.cc b/quiche/quic/moqt/moqt_track_status_stream.cc
index 938325d..d069b28 100644
--- a/quiche/quic/moqt/moqt_track_status_stream.cc
+++ b/quiche/quic/moqt/moqt_track_status_stream.cc
@@ -41,7 +41,6 @@
       response_callback_(std::move(response_callback)) {}
 
 void MoqtTrackStatusRequestStream::OnStreamBound() {
-  stream_parser()->set_allow_fin(true);
   MoqtTrackStatus message;
   message.request_id = request_id_;
   message.full_track_name = full_track_name_;
diff --git a/quiche/quic/moqt/moqt_track_status_stream.h b/quiche/quic/moqt/moqt_track_status_stream.h
index d9c5c6e..79e4b54 100644
--- a/quiche/quic/moqt/moqt_track_status_stream.h
+++ b/quiche/quic/moqt/moqt_track_status_stream.h
@@ -71,7 +71,7 @@
 
   // MoqtBidiStreamBase overrides.
   using MoqtBidiStreamBase::OnControlMessage;
-  void OnStreamBound() override { stream_parser()->set_allow_fin(true); }
+  void OnStreamBound() override {}
   absl::Status OnRawControlMessage(
       const MoqtRawControlMessage& message) override;
   absl::Status OnControlMessage(const MoqtTrackStatus& message);