diff options
author | perkj@chromium.org <perkj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-04 10:01:37 +0000 |
---|---|---|
committer | perkj@chromium.org <perkj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-04 10:01:37 +0000 |
commit | 711e4cb5ac62082a159dfb6f54456f8f552032db (patch) | |
tree | 83aad9ce5b30ae7185c42d9434151f5367e78d15 /content/renderer | |
parent | f36871d4b4fc1dd0762080a942fa7a6610c62652 (diff) | |
download | chromium_src-711e4cb5ac62082a159dfb6f54456f8f552032db.zip chromium_src-711e4cb5ac62082a159dfb6f54456f8f552032db.tar.gz chromium_src-711e4cb5ac62082a159dfb6f54456f8f552032db.tar.bz2 |
Make sure MediaStreamDispatcher gets notified of stopped streams when a WebFrame is deleted.
BUG= 125938
TEST= unit test and html test pages
Review URL: http://codereview.chromium.org/10354009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135311 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
-rw-r--r-- | content/renderer/media/media_stream_impl.cc | 43 | ||||
-rw-r--r-- | content/renderer/media/media_stream_impl.h | 47 | ||||
-rw-r--r-- | content/renderer/media/media_stream_impl_unittest.cc | 10 |
3 files changed, 77 insertions, 23 deletions
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc index 8f43e05..c8d9041 100644 --- a/content/renderer/media/media_stream_impl.cc +++ b/content/renderer/media/media_stream_impl.cc @@ -24,6 +24,7 @@ #include "content/renderer/p2p/socket_dispatcher.h" #include "jingle/glue/thread_wrapper.h" #include "media/base/message_loop_factory.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistry.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamComponent.h" @@ -123,6 +124,7 @@ MediaStreamImpl::MediaStreamImpl( MediaStreamImpl::~MediaStreamImpl() { DCHECK(peer_connection_handlers_.empty()); + DCHECK(local_media_streams_.empty()); if (dependency_factory_.get()) dependency_factory_->ReleasePeerConnectionFactory(); if (network_manager_) { @@ -212,7 +214,7 @@ webrtc::LocalMediaStreamInterface* MediaStreamImpl::GetLocalMediaStream( LocalNativeStreamMap::iterator it = local_media_streams_.find(msm_label); if (it == local_media_streams_.end()) return NULL; - return it->second.get(); + return it->second.stream_.get(); } bool MediaStreamImpl::StopLocalMediaStream( @@ -241,6 +243,7 @@ void MediaStreamImpl::requestUserMedia( int request_id = g_next_request_id++; bool audio = false; bool video = false; + WebKit::WebFrame* frame = NULL; std::string security_origin; // |user_media_request| can't be mocked. So in order to test at all we check @@ -254,6 +257,11 @@ void MediaStreamImpl::requestUserMedia( video = user_media_request.video(); security_origin = UTF16ToUTF8( user_media_request.securityOrigin().toString()); + // Get the WebFrame that requested a MediaStream. + // The frame is needed to tell the MediaStreamDispatcher when a stream goes + // out of scope. + frame = WebKit::WebFrame::frameForCurrentContext(); + DCHECK(frame); } DVLOG(1) << "MediaStreamImpl::generateStream(" << request_id << ", [ " @@ -261,9 +269,8 @@ void MediaStreamImpl::requestUserMedia( << (user_media_request.video() ? " video" : "") << "], " << security_origin << ")"; - user_media_requests_.insert( - std::pair<int, WebKit::WebUserMediaRequest>( - request_id, user_media_request)); + user_media_requests_[request_id] = + UserMediaRequestInfo(frame, user_media_request); media_stream_dispatcher_->GenerateStream( request_id, @@ -330,9 +337,10 @@ void MediaStreamImpl::OnStreamGenerated( return; } - CreateNativeLocalMediaStream(label, audio_source_vector, video_source_vector); + CreateNativeLocalMediaStream(label, it->second.frame_, + audio_source_vector, video_source_vector); - WebKit::WebUserMediaRequest user_media_request(it->second); + WebKit::WebUserMediaRequest user_media_request(it->second.request_); user_media_requests_.erase(it); // |user_media_request| can't be mocked. So in order to test at all we check @@ -351,7 +359,7 @@ void MediaStreamImpl::OnStreamGenerationFailed(int request_id) { DVLOG(1) << "Request ID not found"; return; } - WebKit::WebUserMediaRequest user_media_request = it->second; + WebKit::WebUserMediaRequest user_media_request(it->second.request_); user_media_requests_.erase(it); user_media_request.requestFailed(); @@ -404,6 +412,21 @@ void MediaStreamImpl::OnDeviceOpenFailed(int request_id) { NOTIMPLEMENTED(); } +void MediaStreamImpl::FrameWillClose(WebKit::WebFrame* frame) { + LocalNativeStreamMap::iterator it = local_media_streams_.begin(); + while (it != local_media_streams_.end()) { + if (it->second.frame_ == frame) { + DVLOG(1) << "MediaStreamImpl::FrameWillClose: " + << "Stopping stream " << it->first; + media_stream_dispatcher_->StopStream(it->first); + local_media_streams_.erase(it); + it = local_media_streams_.begin(); + } else { + ++it; + } + } +} + void MediaStreamImpl::InitializeWorkerThread(talk_base::Thread** thread, base::WaitableEvent* event) { jingle_glue::JingleThreadWrapper::EnsureForCurrentThread(); @@ -537,6 +560,7 @@ scoped_refptr<media::VideoDecoder> MediaStreamImpl::CreateRemoteVideoDecoder( void MediaStreamImpl::CreateNativeLocalMediaStream( const std::string& label, + WebKit::WebFrame* frame, const WebKit::WebVector<WebKit::WebMediaStreamSource>& audio_sources, const WebKit::WebVector<WebKit::WebMediaStreamSource>& video_sources) { // Creating the peer connection factory can fail if for example the audio @@ -574,7 +598,7 @@ void MediaStreamImpl::CreateNativeLocalMediaStream( UTF16ToUTF8(video_sources[i].name()), video_session_id)); native_stream->AddTrack(video_track); } - local_media_streams_[label] = native_stream; + local_media_streams_[label] = LocalMediaStreamInfo(frame, native_stream); } MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper( @@ -584,3 +608,6 @@ MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper( MediaStreamImpl::VideoRendererWrapper::~VideoRendererWrapper() { } + +MediaStreamImpl::LocalMediaStreamInfo::~LocalMediaStreamInfo() { +} diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h index 37af40c0..c1206c0 100644 --- a/content/renderer/media/media_stream_impl.h +++ b/content/renderer/media/media_stream_impl.h @@ -44,6 +44,7 @@ class Thread; } namespace WebKit { +class WebFrame; class WebMediaStreamComponent; class WebMediaStreamDescriptor; class WebPeerConnection00Handler; @@ -129,6 +130,9 @@ class CONTENT_EXPORT MediaStreamImpl const media_stream::StreamDeviceInfo& device_info) OVERRIDE; virtual void OnDeviceOpenFailed(int request_id) OVERRIDE; + // content::RenderViewObserver OVERRIDE + virtual void FrameWillClose(WebKit::WebFrame* frame) OVERRIDE; + private: FRIEND_TEST_ALL_PREFIXES(MediaStreamImplTest, Basic); FRIEND_TEST_ALL_PREFIXES(MediaStreamImplTest, MultiplePeerConnections); @@ -148,6 +152,36 @@ class CONTENT_EXPORT MediaStreamImpl scoped_refptr<RTCVideoDecoder> rtc_video_decoder_; }; + // Structure for storing information about a WebKit request to create a + // MediaStream. + struct UserMediaRequestInfo { + UserMediaRequestInfo() : frame_(NULL), request_() {} + UserMediaRequestInfo(WebKit::WebFrame* frame, + const WebKit::WebUserMediaRequest& request) + : frame_(frame), request_(request) {} + WebKit::WebFrame* frame_; // WebFrame that requested the MediaStream. + WebKit::WebUserMediaRequest request_; + }; + typedef std::map<int, UserMediaRequestInfo> MediaRequestMap; + + // We keep a list of the generated local media streams, + // so that we can enable and disable individual tracks and add renderers + // when needed. + typedef talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> + LocalMediaStreamPtr; + struct LocalMediaStreamInfo { + LocalMediaStreamInfo() : frame_(NULL), stream_() {} + LocalMediaStreamInfo(WebKit::WebFrame* frame, + webrtc::LocalMediaStreamInterface* stream) + : frame_(frame), stream_(stream) {} + ~LocalMediaStreamInfo(); + // WebFrame that requested the Stream. + WebKit::WebFrame* frame_; + // Native representation of a local MediaStream. + LocalMediaStreamPtr stream_; + }; + typedef std::map<std::string, LocalMediaStreamInfo> LocalNativeStreamMap; + void InitializeWorkerThread(talk_base::Thread** thread, base::WaitableEvent* event); @@ -168,6 +202,7 @@ class CONTENT_EXPORT MediaStreamImpl media::MessageLoopFactory* message_loop_factory); void CreateNativeLocalMediaStream( const std::string& label, + WebKit::WebFrame* frame, const WebKit::WebVector<WebKit::WebMediaStreamSource>& audio_sources, const WebKit::WebVector<WebKit::WebMediaStreamSource>& video_sources); @@ -184,9 +219,7 @@ class CONTENT_EXPORT MediaStreamImpl // We own network_manager_, must be deleted on the worker thread. // The network manager uses |p2p_socket_dispatcher_|. content::IpcNetworkManager* network_manager_; - scoped_ptr<content::IpcPacketSocketFactory> socket_factory_; - scoped_refptr<VideoCaptureImplManager> vc_manager_; // peer_connection_handlers_ contains raw references, owned by WebKit. A @@ -194,12 +227,7 @@ class CONTENT_EXPORT MediaStreamImpl // ClosePeerConnection on us and we remove the pointer). std::list<PeerConnectionHandlerBase*> peer_connection_handlers_; - // We keep a list of the generated local media streams, - // so that we can enable and disable individual tracks and add renderers - // when needed. - typedef talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> - LocalMediaStreamPtr; - typedef std::map<std::string, LocalMediaStreamPtr> LocalNativeStreamMap; + MediaRequestMap user_media_requests_; LocalNativeStreamMap local_media_streams_; // PeerConnection threads. signaling_thread_ is created from the @@ -208,9 +236,6 @@ class CONTENT_EXPORT MediaStreamImpl talk_base::Thread* worker_thread_; base::Thread chrome_worker_thread_; - typedef std::map<int, WebKit::WebUserMediaRequest> MediaRequestMap; - MediaRequestMap user_media_requests_; - DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl); }; diff --git a/content/renderer/media/media_stream_impl_unittest.cc b/content/renderer/media/media_stream_impl_unittest.cc index 2505910..40797f6 100644 --- a/content/renderer/media/media_stream_impl_unittest.cc +++ b/content/renderer/media/media_stream_impl_unittest.cc @@ -83,8 +83,8 @@ class MediaStreamImplTest : public ::testing::Test { loop_.RunAllPending(); } - WebKit::WebMediaStreamDescriptor RequestLocalMediaStream (bool audio, - bool video) { + WebKit::WebMediaStreamDescriptor RequestLocalMediaStream(bool audio, + bool video) { WebKit::WebUserMediaRequest user_media_request; WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources( audio ? static_cast<size_t>(1) : 0); @@ -220,13 +220,15 @@ TEST_F(MediaStreamImplTest, LocalMediaStream) { message_loop_factory.get())); EXPECT_TRUE(video_decoder.get() != NULL); - // Stop all generated local streams. + // Stop generated local streams. EXPECT_TRUE(ms_impl_->StopLocalMediaStream(mixed_desc)); EXPECT_TRUE(ms_impl_->GetLocalMediaStream(mixed_desc) == NULL); EXPECT_TRUE(ms_impl_->StopLocalMediaStream(audio_desc)); EXPECT_TRUE(ms_impl_->GetLocalMediaStream(audio_desc) == NULL); - EXPECT_TRUE(ms_impl_->StopLocalMediaStream(video_desc)); + // Test that the MediaStreams are deleted if the owning WebFrame is deleted. + // In the unit test the owning frame is NULL. + ms_impl_->FrameWillClose(NULL); EXPECT_TRUE(ms_impl_->GetLocalMediaStream(video_desc) == NULL); } |