[M149] In SctpDataChannel use plain bool as safety flag.

Original change's description:
> In SctpDataChannel use plain bool as safety flag.
>
> SctpDataChannel can be destroyed on various threads and thus safety flag
> couldn't be properly invalidated in the destructor. Instead of relying
> on it when posting async send, rely on reference counting of the full
> object
>
> Bug: chromium:504716948
> Change-Id: I1246fecac26d0761be006b069658d072183546bf
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/469980
> Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#47635}

(cherry picked from commit 9b4ffb3281c02327968ed07389082fcb2dd77baa)

Bug: chromium:514928086,chromium:504716948
Change-Id: I1246fecac26d0761be006b069658d072183546bf
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/474801
Auto-Submit: Chrome Cherry Picker <chrome-cherry-picker@chops-service-accounts.iam.gserviceaccount.com>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/branch-heads/7827@{#3}
Cr-Branched-From: d606bc991592fbf4dcbe85e9d05db5e501a5ad42-refs/heads/main@{#47595}
diff --git a/pc/sctp_data_channel.cc b/pc/sctp_data_channel.cc
index a7338aa..6d7305a 100644
--- a/pc/sctp_data_channel.cc
+++ b/pc/sctp_data_channel.cc
@@ -344,16 +344,14 @@
       negotiated_(config.negotiated),
       ordered_(config.ordered),
       observer_(nullptr),
-      controller_(std::move(controller)) {
+      controller_(std::move(controller)),
+      connected_to_transport_(connected_to_transport) {
   RTC_DCHECK_RUN_ON(network_thread_);
   // Since we constructed on the network thread we can't (yet) check the
   // `controller_` pointer since doing so will trigger a thread check.
   RTC_UNUSED(network_thread_);
   RTC_DCHECK(config.IsValid());
 
-  if (connected_to_transport)
-    network_safety_->SetAlive();
-
   switch (config.open_handshake_role) {
     case InternalDataChannelInit::kNone:  // pre-negotiated
       handshake_state_ = kHandshakeReady;
@@ -611,14 +609,17 @@
   // thread. So we always post to the network thread (even if the current thread
   // might be the network thread - in theory a call could even come from within
   // the `on_complete` callback).
-  network_thread_->PostTask(SafeTask(
-      network_safety_, [this, buffer = std::move(buffer),
-                        on_complete = std::move(on_complete)]() mutable {
-        RTC_DCHECK_RUN_ON(network_thread_);
-        RTCError err = SendImpl(std::move(buffer));
-        if (on_complete)
-          std::move(on_complete)(err);
-      }));
+  scoped_refptr<SctpDataChannel> me(this);
+  network_thread_->PostTask([me = std::move(me), buffer = std::move(buffer),
+                             on_complete = std::move(on_complete)]() mutable {
+    RTC_DCHECK_RUN_ON(me->network_thread_);
+    if (!me->connected_to_transport()) {
+      return;
+    }
+    RTCError err = me->SendImpl(std::move(buffer));
+    if (on_complete)
+      std::move(on_complete)(err);
+  });
 }
 
 void SctpDataChannel::SetSctpSid_n(StreamId sid) {
@@ -661,7 +662,7 @@
 
 void SctpDataChannel::OnTransportChannelCreated() {
   RTC_DCHECK_RUN_ON(network_thread_);
-  network_safety_->SetAlive();
+  connected_to_transport_ = true;
 }
 
 void SctpDataChannel::OnTransportChannelClosed(RTCError error) {
@@ -782,7 +783,7 @@
     return;
   }
 
-  network_safety_->SetNotAlive();
+  connected_to_transport_ = false;
 
   // Still go to "kClosing" before "kClosed", since observers may be expecting
   // that.
diff --git a/pc/sctp_data_channel.h b/pc/sctp_data_channel.h
index 2ac0a3e..693661b 100644
--- a/pc/sctp_data_channel.h
+++ b/pc/sctp_data_channel.h
@@ -273,7 +273,7 @@
       RTC_RUN_ON(network_thread_);
 
   bool connected_to_transport() const RTC_RUN_ON(network_thread_) {
-    return network_safety_->alive();
+    return connected_to_transport_;
   }
   void MaybeSendOnBufferedAmountChanged() RTC_RUN_ON(network_thread_);
 
@@ -306,9 +306,8 @@
       kHandshakeInit;
   // Did we already start the graceful SCTP closing procedure?
   bool started_closing_procedure_ RTC_GUARDED_BY(network_thread_) = false;
+  bool connected_to_transport_ RTC_GUARDED_BY(network_thread_) = false;
   PacketQueue queued_received_data_ RTC_GUARDED_BY(network_thread_);
-  scoped_refptr<PendingTaskSafetyFlag> network_safety_ =
-      PendingTaskSafetyFlag::CreateDetachedInactive();
 };
 
 }  // namespace webrtc
diff --git a/pc/sctp_data_channel_unittest.cc b/pc/sctp_data_channel_unittest.cc
index 06b4a88..c4e30ee 100644
--- a/pc/sctp_data_channel_unittest.cc
+++ b/pc/sctp_data_channel_unittest.cc
@@ -613,6 +613,22 @@
   EXPECT_EQ(RTCErrorDetailType::SCTP_FAILURE, channel_->error().error_detail());
 }
 
+TEST_F(SctpDataChannelTest, ChannelDeletedWhileDataBuffered) {
+  AddObserver();
+  SetChannelReady();
+
+  CopyOnWriteBuffer buffer(100 * 1024);
+  memset(buffer.MutableData(), 0, buffer.size());
+  DataBuffer packet(buffer, true);
+
+  // Send a very large packet, forcing the message to become buffered.
+  channel_->SendAsync(packet, nullptr);
+
+  // Delete the channel, expect no crashes.
+  inner_channel_ = nullptr;
+  channel_ = nullptr;
+}
+
 TEST_F(SctpDataChannelTest, TransportGotErrorCode) {
   SetChannelReady();