diff --git a/talk/app/webrtc/objc/RTCPeerConnectionObserver.h b/talk/app/webrtc/objc/RTCPeerConnectionObserver.h index 2bb35550fe..9edcc82f07 100644 --- a/talk/app/webrtc/objc/RTCPeerConnectionObserver.h +++ b/talk/app/webrtc/objc/RTCPeerConnectionObserver.h @@ -39,7 +39,9 @@ class RTCPeerConnectionObserver : public PeerConnectionObserver { public: explicit RTCPeerConnectionObserver(id delegate); + virtual ~RTCPeerConnectionObserver(); + // |peerConnection| owns |this|, so outlives it. void SetPeerConnection(RTCPeerConnection *peerConnection); virtual void OnError() OVERRIDE; @@ -73,7 +75,9 @@ class RTCPeerConnectionObserver : public PeerConnectionObserver { private: id _delegate; - RTCPeerConnection *_peerConnection; + // __unsafe_unretained is in fact safe because |_peerConnection| owns |this|; + // see comment on SetPeerConnection() above. + __unsafe_unretained RTCPeerConnection *_peerConnection; }; } // namespace webrtc diff --git a/talk/app/webrtc/objc/RTCPeerConnectionObserver.mm b/talk/app/webrtc/objc/RTCPeerConnectionObserver.mm index d9b9b42aed..5fb098f44f 100644 --- a/talk/app/webrtc/objc/RTCPeerConnectionObserver.mm +++ b/talk/app/webrtc/objc/RTCPeerConnectionObserver.mm @@ -42,6 +42,8 @@ RTCPeerConnectionObserver::RTCPeerConnectionObserver( _delegate = delegate; } +RTCPeerConnectionObserver::~RTCPeerConnectionObserver() {} + void RTCPeerConnectionObserver::SetPeerConnection( RTCPeerConnection* peerConnection) { _peerConnection = peerConnection; diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m b/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m index 645fb778e7..65684033c3 100644 --- a/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m +++ b/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m @@ -183,7 +183,7 @@ } - (void)peerConnection:(RTCPeerConnection*)peerConnection - iceConnectionChanged:(RTCICEConnectionState)newState { + iceConnectionChanged:(RTCICEConnectionState)newState { // See TODO(fischman) in RTCPeerConnectionTest.mm about Completed. if (newState == RTCICEConnectionCompleted) return; diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm index 9a0291411a..b46df7f418 100644 --- a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm +++ b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm @@ -59,7 +59,7 @@ videoTrackID:(NSString*)videoTrackID audioTrackID:(NSString*)audioTrackID; -- (void)testCompleteSession; +- (void)testCompleteSessionWithFactory:(RTCPeerConnectionFactory*)factory; @end @@ -93,8 +93,7 @@ return localMediaStream; } -- (void)testCompleteSession { - RTCPeerConnectionFactory* factory = [[RTCPeerConnectionFactory alloc] init]; +- (void)testCompleteSessionWithFactory:(RTCPeerConnectionFactory*)factory { RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] init]; RTCPeerConnectionSyncObserver* offeringExpectations = [[RTCPeerConnectionSyncObserver alloc] init]; @@ -216,7 +215,24 @@ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; - // TODO(hughv): Implement orderly shutdown. + [offeringExpectations expectICEConnectionChange:RTCICEConnectionClosed]; + [answeringExpectations expectICEConnectionChange:RTCICEConnectionClosed]; + [offeringExpectations expectSignalingChange:RTCSignalingClosed]; + [answeringExpectations expectSignalingChange:RTCSignalingClosed]; + + [pcOffer close]; + [pcAnswer close]; + + [offeringExpectations waitForAllExpectationsToBeSatisfied]; + [answeringExpectations waitForAllExpectationsToBeSatisfied]; + + capturer = nil; + videoSource = nil; + pcOffer = nil; + pcAnswer = nil; + // TODO(fischman): be stricter about shutdown checks; ensure thread + // counts return to where they were before the test kicked off, and + // that all objects have in fact shut down. } @end @@ -225,8 +241,20 @@ // RTCPeerConnectionTest and avoid the appearance of RTCPeerConnectionTest being // a TestBase since it's not. TEST(RTCPeerConnectionTest, SessionTest) { - talk_base::InitializeSSL(); - RTCPeerConnectionTest* pcTest = [[RTCPeerConnectionTest alloc] init]; - [pcTest testCompleteSession]; - talk_base::CleanupSSL(); + @autoreleasepool { + talk_base::InitializeSSL(); + // Since |factory| will own the signaling & worker threads, it's important + // that it outlive the created PeerConnections since they self-delete on the + // signaling thread, and if |factory| is freed first then a last refcount on + // the factory will expire during this teardown, causing the signaling + // thread to try to Join() with itself. This is a hack to ensure that the + // factory outlives RTCPeerConnection:dealloc. + // See https://code.google.com/p/webrtc/issues/detail?id=3100. + RTCPeerConnectionFactory* factory = [[RTCPeerConnectionFactory alloc] init]; + @autoreleasepool { + RTCPeerConnectionTest* pcTest = [[RTCPeerConnectionTest alloc] init]; + [pcTest testCompleteSessionWithFactory:factory]; + } + talk_base::CleanupSSL(); + } } diff --git a/talk/app/webrtc/objctests/mac/main.mm b/talk/app/webrtc/objctests/mac/main.mm index c44b977060..4995b7f3ac 100644 --- a/talk/app/webrtc/objctests/mac/main.mm +++ b/talk/app/webrtc/objctests/mac/main.mm @@ -27,6 +27,10 @@ #include "talk/base/gunit.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + int main(int argc, char* argv[]) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h index 517cade8db..3e6d600bb4 100644 --- a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h +++ b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h @@ -30,7 +30,7 @@ #import "GAEChannelClient.h" #import "APPRTCAppClient.h" #import "RTCSessionDescriptonDelegate.h" - +#import "RTCVideoSource.h" // Used to send a message to an apprtc.appspot.com "room". @protocol APPRTCSendMessage @@ -43,7 +43,7 @@ @class RTCVideoTrack; // The main application class of the AppRTCDemo iOS app demonstrating -// interoperability between the Objcective C implementation of PeerConnection +// interoperability between the Objective C implementation of PeerConnection // and the apprtc.appspot.com demo webapp. @interface APPRTCAppDelegate : UIResponder