Fixed crash when PCF is destroyed before RTCRtpSender in ObjC

Bug: webrtc:9231
Change-Id: I3b90400bf619938817d7a04a7a1130ba86ad65df
Reviewed-on: https://webrtc-review.googlesource.com/87623
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23896}
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
index f6b2343..c61e0e1 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
@@ -386,7 +386,8 @@
     RTCLogError(@"Failed to add track %@: %s", track, nativeSenderOrError.error().message());
     return nil;
   }
-  return [[RTCRtpSender alloc] initWithNativeRtpSender:nativeSenderOrError.MoveValue()];
+  return [[RTCRtpSender alloc] initWithFactory:self.factory
+                               nativeRtpSender:nativeSenderOrError.MoveValue()];
 }
 
 - (BOOL)removeTrack:(RTCRtpSender *)sender {
@@ -522,8 +523,8 @@
   rtc::scoped_refptr<webrtc::RtpSenderInterface> nativeSender(
       _peerConnection->CreateSender(nativeKind, nativeStreamId));
   return nativeSender ?
-      [[RTCRtpSender alloc] initWithNativeRtpSender:nativeSender]
-      : nil;
+      [[RTCRtpSender alloc] initWithFactory:self.factory nativeRtpSender:nativeSender] :
+      nil;
 }
 
 - (NSArray<RTCRtpSender *> *)senders {
@@ -532,7 +533,7 @@
   NSMutableArray *senders = [[NSMutableArray alloc] init];
   for (const auto &nativeSender : nativeSenders) {
     RTCRtpSender *sender =
-        [[RTCRtpSender alloc] initWithNativeRtpSender:nativeSender];
+        [[RTCRtpSender alloc] initWithFactory:self.factory nativeRtpSender:nativeSender];
     [senders addObject:sender];
   }
   return senders;
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender+Private.h
index 7164bca..5b671ae 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender+Private.h
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender+Private.h
@@ -14,13 +14,16 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+@class RTCPeerConnectionFactory;
+
 @interface RTCRtpSender ()
 
 @property(nonatomic, readonly) rtc::scoped_refptr<webrtc::RtpSenderInterface> nativeRtpSender;
 
 /** Initialize an RTCRtpSender with a native RtpSenderInterface. */
-- (instancetype)initWithNativeRtpSender:
-        (rtc::scoped_refptr<webrtc::RtpSenderInterface>)nativeRtpSender NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithFactory:(RTCPeerConnectionFactory*)factory
+                nativeRtpSender:(rtc::scoped_refptr<webrtc::RtpSenderInterface>)nativeRtpSender
+    NS_DESIGNATED_INITIALIZER;
 
 @end
 
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender.mm
index e980ade..1df7ae5 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpSender.mm
@@ -19,6 +19,7 @@
 #include "api/mediastreaminterface.h"
 
 @implementation RTCRtpSender {
+  RTCPeerConnectionFactory *_factory;
   rtc::scoped_refptr<webrtc::RtpSenderInterface> _nativeRtpSender;
 }
 
@@ -84,10 +85,12 @@
   return _nativeRtpSender;
 }
 
-- (instancetype)initWithNativeRtpSender:
-    (rtc::scoped_refptr<webrtc::RtpSenderInterface>)nativeRtpSender {
+- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
+                nativeRtpSender:(rtc::scoped_refptr<webrtc::RtpSenderInterface>)nativeRtpSender {
+  NSParameterAssert(factory);
   NSParameterAssert(nativeRtpSender);
   if (self = [super init]) {
+    _factory = factory;
     _nativeRtpSender = nativeRtpSender;
     rtc::scoped_refptr<webrtc::DtmfSenderInterface> nativeDtmfSender(
         _nativeRtpSender->GetDtmfSender());
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm
index 780fcd5..ea4b3a9 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm
@@ -129,7 +129,8 @@
   if (self = [super init]) {
     _factory = factory;
     _nativeRtpTransceiver = nativeRtpTransceiver;
-    _sender = [[RTCRtpSender alloc] initWithNativeRtpSender:nativeRtpTransceiver->sender()];
+    _sender = [[RTCRtpSender alloc] initWithFactory:_factory
+                                    nativeRtpSender:nativeRtpTransceiver->sender()];
     _receiver = [[RTCRtpReceiver alloc] initWithNativeRtpReceiver:nativeRtpTransceiver->receiver()];
     RTCLogInfo(@"RTCRtpTransceiver(%p): created transceiver: %@", self, self.description);
   }
diff --git a/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m b/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
index 4e679fa..b5f3b98 100644
--- a/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
+++ b/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
@@ -12,8 +12,10 @@
 #import <WebRTC/RTCDataChannel.h>
 #import <WebRTC/RTCDataChannelConfiguration.h>
 #import <WebRTC/RTCMediaConstraints.h>
+#import <WebRTC/RTCMediaStreamTrack.h>
 #import <WebRTC/RTCPeerConnection.h>
 #import <WebRTC/RTCPeerConnectionFactory.h>
+#import <WebRTC/RTCRtpSender.h>
 #import <WebRTC/RTCRtpTransceiver.h>
 
 #import <XCTest/XCTest.h>
@@ -119,4 +121,30 @@
   XCTAssertTrue(true, "Expect test does not crash");
 }
 
+- (void)testRTCRtpSenderLifetime {
+  @autoreleasepool {
+    RTCConfiguration *config = [[RTCConfiguration alloc] init];
+    RTCMediaConstraints *contraints =
+        [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
+
+    RTCPeerConnectionFactory *factory;
+    RTCPeerConnection *peerConnection;
+    RTCRtpSender *sender;
+
+    @autoreleasepool {
+      factory = [[RTCPeerConnectionFactory alloc] init];
+      peerConnection =
+          [factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
+      sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo streamId:@"stream"];
+      XCTAssertTrue(sender != nil);
+      [peerConnection close];
+      peerConnection = nil;
+      factory = nil;
+    }
+    sender = nil;
+  }
+
+  XCTAssertTrue(true, "Expect test does not crash");
+}
+
 @end