Fixed crash when PCF is destroyed before MediaStream in ObjC

Bug: webrtc:9231
Change-Id: I04e76172dd0d5ee5e9040e773e63fd4df0c797ce
Reviewed-on: https://webrtc-review.googlesource.com/84580
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23699}
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream+Private.h
index f95d15c..3986066 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream+Private.h
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream+Private.h
@@ -26,8 +26,8 @@
 - (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory streamId:(NSString *)streamId;
 
 /** Initialize an RTCMediaStream from a native MediaStreamInterface. */
-- (instancetype)initWithNativeMediaStream:
-        (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream;
+- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
+              nativeMediaStream:(rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream;
 
 @end
 
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream.mm
index ff0cbf5..52f1771 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCMediaStream.mm
@@ -19,6 +19,7 @@
 #import "RTCVideoTrack+Private.h"
 
 @implementation RTCMediaStream {
+  RTCPeerConnectionFactory *_factory;
   NSMutableArray *_audioTracks;
   NSMutableArray *_videoTracks;
   rtc::scoped_refptr<webrtc::MediaStreamInterface> _nativeMediaStream;
@@ -31,7 +32,7 @@
   std::string nativeId = [NSString stdStringForString:streamId];
   rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
       factory.nativeFactory->CreateLocalMediaStream(nativeId);
-  return [self initWithNativeMediaStream:stream];
+  return [self initWithFactory:factory nativeMediaStream:stream];
 }
 
 - (NSArray<RTCAudioTrack *> *)audioTracks {
@@ -91,10 +92,13 @@
   return _nativeMediaStream;
 }
 
-- (instancetype)initWithNativeMediaStream:
-    (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream {
+- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
+              nativeMediaStream:
+                  (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream {
   NSParameterAssert(nativeMediaStream);
   if (self = [super init]) {
+    _factory = factory;
+
     webrtc::AudioTrackVector audioTracks = nativeMediaStream->GetAudioTracks();
     webrtc::VideoTrackVector videoTracks = nativeMediaStream->GetVideoTracks();
 
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection+Private.h b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection+Private.h
index f533605..15b05de 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection+Private.h
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection+Private.h
@@ -56,6 +56,9 @@
 
 @interface RTCPeerConnection ()
 
+/** The factory used to create this RTCPeerConnection */
+@property(nonatomic, readonly) RTCPeerConnectionFactory *factory;
+
 /** The native PeerConnectionInterface created during construction. */
 @property(nonatomic, readonly) rtc::scoped_refptr<webrtc::PeerConnectionInterface>
     nativePeerConnection;
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
index bea0ede..8d10c34 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCPeerConnection.mm
@@ -132,18 +132,19 @@
 
 void PeerConnectionDelegateAdapter::OnAddStream(
     rtc::scoped_refptr<MediaStreamInterface> stream) {
-  RTCMediaStream *mediaStream =
-      [[RTCMediaStream alloc] initWithNativeMediaStream:stream];
   RTCPeerConnection *peer_connection = peer_connection_;
+  RTCMediaStream *mediaStream =
+      [[RTCMediaStream alloc] initWithFactory:peer_connection.factory nativeMediaStream:stream];
   [peer_connection.delegate peerConnection:peer_connection
                               didAddStream:mediaStream];
 }
 
 void PeerConnectionDelegateAdapter::OnRemoveStream(
     rtc::scoped_refptr<MediaStreamInterface> stream) {
-  RTCMediaStream *mediaStream =
-      [[RTCMediaStream alloc] initWithNativeMediaStream:stream];
   RTCPeerConnection *peer_connection = peer_connection_;
+  RTCMediaStream *mediaStream =
+      [[RTCMediaStream alloc] initWithFactory:peer_connection.factory nativeMediaStream:stream];
+
   [peer_connection.delegate peerConnection:peer_connection
                            didRemoveStream:mediaStream];
 }
@@ -225,7 +226,8 @@
           respondsToSelector:@selector(peerConnection:didAddReceiver:streams:)]) {
     NSMutableArray *mediaStreams = [NSMutableArray arrayWithCapacity:streams.size()];
     for (const auto& nativeStream : streams) {
-      RTCMediaStream *mediaStream = [[RTCMediaStream alloc] initWithNativeMediaStream:nativeStream];
+      RTCMediaStream *mediaStream = [[RTCMediaStream alloc] initWithFactory:peer_connection.factory
+                                                          nativeMediaStream:nativeStream];
       [mediaStreams addObject:mediaStream];
     }
     RTCRtpReceiver *rtpReceiver = [[RTCRtpReceiver alloc] initWithNativeRtpReceiver:receiver];
@@ -249,6 +251,7 @@
 }
 
 @synthesize delegate = _delegate;
+@synthesize factory = _factory;
 
 - (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
                   configuration:(RTCConfiguration *)configuration
diff --git a/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m b/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
index 1c678d6..f8eb89a 100644
--- a/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
+++ b/sdk/objc/Framework/UnitTests/RTCPeerConnectionFactory_xctest.m
@@ -28,18 +28,36 @@
     RTCMediaConstraints *contraints =
         [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil];
 
-    RTCPeerConnectionFactory *factory = [[RTCPeerConnectionFactory alloc] init];
+    RTCPeerConnectionFactory *factory;
+    RTCPeerConnection *peerConnection;
 
-    RTCPeerConnection *peerConnection =
-        [factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
-
-    [peerConnection close];
-
-    factory = nil;
+    @autoreleasepool {
+      factory = [[RTCPeerConnectionFactory alloc] init];
+      peerConnection =
+          [factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil];
+      [peerConnection close];
+      factory = nil;
+    }
     peerConnection = nil;
   }
 
   XCTAssertTrue(true, @"Expect test does not crash");
 }
 
+- (void)testMediaStreamLifetime {
+  @autoreleasepool {
+    RTCPeerConnectionFactory *factory;
+    RTCMediaStream *mediaStream;
+
+    @autoreleasepool {
+      factory = [[RTCPeerConnectionFactory alloc] init];
+      mediaStream = [factory mediaStreamWithStreamId:@"mediaStream"];
+      factory = nil;
+    }
+    mediaStream = nil;
+  }
+
+  XCTAssertTrue(true, "Expect test does not crash");
+}
+
 @end