Fixed crash when PCF is destroyed before RTCRtpTranceiver in ObjC

Bug: webrtc:9231
Change-Id: Icecc319eaf6edd2c4b7b05fda984660412cb0d40
Reviewed-on: https://webrtc-review.googlesource.com/87439
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23884}
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
index b5c8cba..f6b2343 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
@@ -151,9 +151,10 @@
 
 void PeerConnectionDelegateAdapter::OnTrack(
     rtc::scoped_refptr<RtpTransceiverInterface> nativeTransceiver) {
-  RTCRtpTransceiver *transceiver =
-      [[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiver];
   RTCPeerConnection *peer_connection = peer_connection_;
+  RTCRtpTransceiver *transceiver =
+      [[RTCRtpTransceiver alloc] initWithFactory:peer_connection.factory
+                            nativeRtpTransceiver:nativeTransceiver];
   if ([peer_connection.delegate
           respondsToSelector:@selector(peerConnection:didStartReceivingOnTransceiver:)]) {
     [peer_connection.delegate peerConnection:peer_connection
@@ -409,8 +410,8 @@
         @"Failed to add transceiver %@: %s", track, nativeTransceiverOrError.error().message());
     return nil;
   }
-  return
-      [[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
+  return [[RTCRtpTransceiver alloc] initWithFactory:self.factory
+                               nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
 }
 
 - (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType {
@@ -428,8 +429,8 @@
                 nativeTransceiverOrError.error().message());
     return nil;
   }
-  return
-      [[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
+  return [[RTCRtpTransceiver alloc] initWithFactory:self.factory
+                               nativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
 }
 
 - (void)offerForConstraints:(RTCMediaConstraints *)constraints
@@ -554,8 +555,8 @@
       _peerConnection->GetTransceivers());
   NSMutableArray *transceivers = [[NSMutableArray alloc] init];
   for (auto nativeTransceiver : nativeTransceivers) {
-    RTCRtpTransceiver *transceiver =
-        [[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiver];
+    RTCRtpTransceiver *transceiver = [[RTCRtpTransceiver alloc] initWithFactory:self.factory
+                                                           nativeRtpTransceiver:nativeTransceiver];
     [transceivers addObject:transceiver];
   }
   return transceivers;
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver+Private.h
index cc1f4fe..ee361ea 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver+Private.h
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver+Private.h
@@ -14,6 +14,8 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+@class RTCPeerConnectionFactory;
+
 @interface RTCRtpTransceiverInit ()
 
 @property(nonatomic, readonly) webrtc::RtpTransceiverInit nativeInit;
@@ -26,8 +28,9 @@
     nativeRtpTransceiver;
 
 /** Initialize an RTCRtpTransceiver with a native RtpTransceiverInterface. */
-- (instancetype)initWithNativeRtpTransceiver:
-        (rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver
+- (instancetype)initWithFactory:(RTCPeerConnectionFactory*)factory
+           nativeRtpTransceiver:
+               (rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver
     NS_DESIGNATED_INITIALIZER;
 
 + (webrtc::RtpTransceiverDirection)nativeRtpTransceiverDirectionFromDirection:
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm
index 5fe7569..780fcd5 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCRtpTransceiver.mm
@@ -45,6 +45,7 @@
 @end
 
 @implementation RTCRtpTransceiver {
+  RTCPeerConnectionFactory *_factory;
   rtc::scoped_refptr<webrtc::RtpTransceiverInterface> _nativeRtpTransceiver;
 }
 
@@ -120,10 +121,13 @@
   return _nativeRtpTransceiver;
 }
 
-- (instancetype)initWithNativeRtpTransceiver:
-        (rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver {
+- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
+           nativeRtpTransceiver:
+               (rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver {
+  NSParameterAssert(factory);
   NSParameterAssert(nativeRtpTransceiver);
   if (self = [super init]) {
+    _factory = factory;
     _nativeRtpTransceiver = nativeRtpTransceiver;
     _sender = [[RTCRtpSender alloc] initWithNativeRtpSender:nativeRtpTransceiver->sender()];
     _receiver = [[RTCRtpReceiver alloc] initWithNativeRtpReceiver:nativeRtpTransceiver->receiver()];
diff --git a/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m b/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
index f33b218..4e679fa 100644
--- a/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
+++ b/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
@@ -14,6 +14,7 @@
 #import <WebRTC/RTCMediaConstraints.h>
 #import <WebRTC/RTCPeerConnection.h>
 #import <WebRTC/RTCPeerConnectionFactory.h>
+#import <WebRTC/RTCRtpTransceiver.h>
 
 #import <XCTest/XCTest.h>
 
@@ -90,4 +91,32 @@
   XCTAssertTrue(true, "Expect test does not crash");
 }
 
+- (void)testRTCRtpTransceiverLifetime {
+  @autoreleasepool {
+    RTCConfiguration *config = [[RTCConfiguration alloc] init];
+    config.sdpSemantics = RTCSdpSemanticsUnifiedPlan;
+    RTCMediaConstraints *contraints =
+        [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
+    RTCRtpTransceiverInit *init = [[RTCRtpTransceiverInit alloc] init];
+
+    RTCPeerConnectionFactory *factory;
+    RTCPeerConnection *peerConnection;
+    RTCRtpTransceiver *tranceiver;
+
+    @autoreleasepool {
+      factory = [[RTCPeerConnectionFactory alloc] init];
+      peerConnection =
+          [factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
+      tranceiver = [peerConnection addTransceiverOfType:RTCRtpMediaTypeAudio init:init];
+      XCTAssertTrue(tranceiver != nil);
+      [peerConnection close];
+      peerConnection = nil;
+      factory = nil;
+    }
+    tranceiver = nil;
+  }
+
+  XCTAssertTrue(true, "Expect test does not crash");
+}
+
 @end