Commit 9b953806 authored by jiayl@chromium.org's avatar jiayl@chromium.org

Fix for closing the desktop sharing notification bar when the shared window is closed.

Previously MediaStreamManager is not notified when a video capturing device has stopped due to error (e.g. the shared window is closed), so the notification UI is still shown when the stream already stopped.
This change fixes it by populating the state to MediaStreamManager through VideoCaptureHost --> VidoeCaptureManager --> MediaStreamProviderListner.

BUG=360181

Review URL: https://codereview.chromium.org/248113003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267045 0039d316-1c4b-4281-b951-d872f2087c98
parent 673b8465
...@@ -33,7 +33,7 @@ class MockAudioInputDeviceManagerListener ...@@ -33,7 +33,7 @@ class MockAudioInputDeviceManagerListener
MOCK_METHOD2(Closed, void(MediaStreamType, const int)); MOCK_METHOD2(Closed, void(MediaStreamType, const int));
MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType, MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType,
const StreamDeviceInfoArray&)); const StreamDeviceInfoArray&));
MOCK_METHOD3(Error, void(MediaStreamType, int, MediaStreamProviderError)); MOCK_METHOD2(Aborted, void(MediaStreamType, int));
StreamDeviceInfoArray devices_; StreamDeviceInfoArray devices_;
......
...@@ -1620,6 +1620,14 @@ void MediaStreamManager::DevicesEnumerated( ...@@ -1620,6 +1620,14 @@ void MediaStreamManager::DevicesEnumerated(
DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
} }
void MediaStreamManager::Aborted(MediaStreamType stream_type,
int capture_session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "Aborted({stream_type = " << stream_type << "} "
<< "{capture_session_id = " << capture_session_id << "})";
StopDevice(stream_type, capture_session_id);
}
// static // static
void MediaStreamManager::SendMessageToNativeLog(const std::string& message) { void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
BrowserThread::PostTask( BrowserThread::PostTask(
......
...@@ -159,6 +159,8 @@ class CONTENT_EXPORT MediaStreamManager ...@@ -159,6 +159,8 @@ class CONTENT_EXPORT MediaStreamManager
int capture_session_id) OVERRIDE; int capture_session_id) OVERRIDE;
virtual void DevicesEnumerated(MediaStreamType stream_type, virtual void DevicesEnumerated(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices) OVERRIDE; const StreamDeviceInfoArray& devices) OVERRIDE;
virtual void Aborted(MediaStreamType stream_type,
int capture_session_id) OVERRIDE;
// Implements base::SystemMonitor::DevicesChangedObserver. // Implements base::SystemMonitor::DevicesChangedObserver.
virtual void OnDevicesChanged( virtual void OnDevicesChanged(
......
...@@ -50,6 +50,10 @@ class CONTENT_EXPORT MediaStreamProviderListener { ...@@ -50,6 +50,10 @@ class CONTENT_EXPORT MediaStreamProviderListener {
virtual void DevicesEnumerated(MediaStreamType stream_type, virtual void DevicesEnumerated(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices) = 0; const StreamDeviceInfoArray& devices) = 0;
// Called by a MediaStreamProvider when the device has been aborted due to
// device error.
virtual void Aborted(MediaStreamType stream_type, int capture_session_id) = 0;
protected: protected:
virtual ~MediaStreamProviderListener() {} virtual ~MediaStreamProviderListener() {}
}; };
......
...@@ -27,7 +27,7 @@ void VideoCaptureHost::OnChannelClosing() { ...@@ -27,7 +27,7 @@ void VideoCaptureHost::OnChannelClosing() {
if (controller) { if (controller) {
VideoCaptureControllerID controller_id(it->first); VideoCaptureControllerID controller_id(it->first);
media_stream_manager_->video_capture_manager()->StopCaptureForClient( media_stream_manager_->video_capture_manager()->StopCaptureForClient(
controller.get(), controller_id, this); controller.get(), controller_id, this, false);
++it; ++it;
} else { } else {
// Remove the entry for this controller_id so that when the controller // Remove the entry for this controller_id so that when the controller
...@@ -177,7 +177,7 @@ void VideoCaptureHost::DoHandleErrorOnIOThread( ...@@ -177,7 +177,7 @@ void VideoCaptureHost::DoHandleErrorOnIOThread(
Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
VIDEO_CAPTURE_STATE_ERROR)); VIDEO_CAPTURE_STATE_ERROR));
DeleteVideoCaptureControllerOnIOThread(controller_id); DeleteVideoCaptureControllerOnIOThread(controller_id, true);
} }
void VideoCaptureHost::DoEndedOnIOThread( void VideoCaptureHost::DoEndedOnIOThread(
...@@ -189,7 +189,7 @@ void VideoCaptureHost::DoEndedOnIOThread( ...@@ -189,7 +189,7 @@ void VideoCaptureHost::DoEndedOnIOThread(
Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
VIDEO_CAPTURE_STATE_ENDED)); VIDEO_CAPTURE_STATE_ENDED));
DeleteVideoCaptureControllerOnIOThread(controller_id); DeleteVideoCaptureControllerOnIOThread(controller_id, false);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -261,7 +261,7 @@ void VideoCaptureHost::DoControllerAddedOnIOThread( ...@@ -261,7 +261,7 @@ void VideoCaptureHost::DoControllerAddedOnIOThread(
if (it == entries_.end()) { if (it == entries_.end()) {
if (controller) { if (controller) {
media_stream_manager_->video_capture_manager()->StopCaptureForClient( media_stream_manager_->video_capture_manager()->StopCaptureForClient(
controller.get(), controller_id, this); controller.get(), controller_id, this, false);
} }
return; return;
} }
...@@ -285,7 +285,7 @@ void VideoCaptureHost::OnStopCapture(int device_id) { ...@@ -285,7 +285,7 @@ void VideoCaptureHost::OnStopCapture(int device_id) {
Send(new VideoCaptureMsg_StateChanged(device_id, Send(new VideoCaptureMsg_StateChanged(device_id,
VIDEO_CAPTURE_STATE_STOPPED)); VIDEO_CAPTURE_STATE_STOPPED));
DeleteVideoCaptureControllerOnIOThread(controller_id); DeleteVideoCaptureControllerOnIOThread(controller_id, false);
} }
void VideoCaptureHost::OnPauseCapture(int device_id) { void VideoCaptureHost::OnPauseCapture(int device_id) {
...@@ -344,7 +344,7 @@ void VideoCaptureHost::OnGetDeviceFormatsInUse( ...@@ -344,7 +344,7 @@ void VideoCaptureHost::OnGetDeviceFormatsInUse(
} }
void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
const VideoCaptureControllerID& controller_id) { const VideoCaptureControllerID& controller_id, bool on_error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
EntryMap::iterator it = entries_.find(controller_id); EntryMap::iterator it = entries_.find(controller_id);
...@@ -353,7 +353,7 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( ...@@ -353,7 +353,7 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
if (it->second) { if (it->second) {
media_stream_manager_->video_capture_manager()->StopCaptureForClient( media_stream_manager_->video_capture_manager()->StopCaptureForClient(
it->second.get(), controller_id, this); it->second.get(), controller_id, this, on_error);
} }
entries_.erase(it); entries_.erase(it);
} }
......
...@@ -140,7 +140,7 @@ class CONTENT_EXPORT VideoCaptureHost ...@@ -140,7 +140,7 @@ class CONTENT_EXPORT VideoCaptureHost
int device_id, int device_id,
media::VideoCaptureSessionId capture_session_id); media::VideoCaptureSessionId capture_session_id);
// Send a newly created buffer to the VideoCaptureMessageFilter. // Sends a newly created buffer to the VideoCaptureMessageFilter.
void DoSendNewBufferOnIOThread( void DoSendNewBufferOnIOThread(
const VideoCaptureControllerID& controller_id, const VideoCaptureControllerID& controller_id,
base::SharedMemoryHandle handle, base::SharedMemoryHandle handle,
...@@ -151,14 +151,14 @@ class CONTENT_EXPORT VideoCaptureHost ...@@ -151,14 +151,14 @@ class CONTENT_EXPORT VideoCaptureHost
const VideoCaptureControllerID& controller_id, const VideoCaptureControllerID& controller_id,
int buffer_id); int buffer_id);
// Send a filled buffer to the VideoCaptureMessageFilter. // Sends a filled buffer to the VideoCaptureMessageFilter.
void DoSendFilledBufferOnIOThread( void DoSendFilledBufferOnIOThread(
const VideoCaptureControllerID& controller_id, const VideoCaptureControllerID& controller_id,
int buffer_id, int buffer_id,
const media::VideoCaptureFormat& format, const media::VideoCaptureFormat& format,
base::TimeTicks timestamp); base::TimeTicks timestamp);
// Send a filled texture mailbox buffer to the VideoCaptureMessageFilter. // Sends a filled texture mailbox buffer to the VideoCaptureMessageFilter.
void DoSendFilledMailboxBufferOnIOThread( void DoSendFilledMailboxBufferOnIOThread(
const VideoCaptureControllerID& controller_id, const VideoCaptureControllerID& controller_id,
int buffer_id, int buffer_id,
...@@ -166,13 +166,15 @@ class CONTENT_EXPORT VideoCaptureHost ...@@ -166,13 +166,15 @@ class CONTENT_EXPORT VideoCaptureHost
const media::VideoCaptureFormat& format, const media::VideoCaptureFormat& format,
base::TimeTicks timestamp); base::TimeTicks timestamp);
// Handle error coming from VideoCaptureDevice. // Handles error coming from VideoCaptureDevice.
void DoHandleErrorOnIOThread(const VideoCaptureControllerID& controller_id); void DoHandleErrorOnIOThread(const VideoCaptureControllerID& controller_id);
void DoEndedOnIOThread(const VideoCaptureControllerID& controller_id); void DoEndedOnIOThread(const VideoCaptureControllerID& controller_id);
// Deletes the controller and notifies the VideoCaptureManager. |on_error| is
// true if this is triggered by VideoCaptureControllerEventHandler::OnError.
void DeleteVideoCaptureControllerOnIOThread( void DeleteVideoCaptureControllerOnIOThread(
const VideoCaptureControllerID& controller_id); const VideoCaptureControllerID& controller_id, bool on_error);
MediaStreamManager* media_stream_manager_; MediaStreamManager* media_stream_manager_;
......
...@@ -158,8 +158,7 @@ void VideoCaptureManager::Close(int capture_session_id) { ...@@ -158,8 +158,7 @@ void VideoCaptureManager::Close(int capture_session_id) {
DCHECK(listener_); DCHECK(listener_);
DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator SessionMap::iterator session_it = sessions_.find(capture_session_id);
session_it = sessions_.find(capture_session_id);
if (session_it == sessions_.end()) { if (session_it == sessions_.end()) {
NOTREACHED(); NOTREACHED();
return; return;
...@@ -289,7 +288,8 @@ void VideoCaptureManager::StartCaptureForClient( ...@@ -289,7 +288,8 @@ void VideoCaptureManager::StartCaptureForClient(
void VideoCaptureManager::StopCaptureForClient( void VideoCaptureManager::StopCaptureForClient(
VideoCaptureController* controller, VideoCaptureController* controller,
VideoCaptureControllerID client_id, VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler) { VideoCaptureControllerEventHandler* client_handler,
bool aborted_due_to_error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(controller); DCHECK(controller);
DCHECK(client_handler); DCHECK(client_handler);
...@@ -299,6 +299,16 @@ void VideoCaptureManager::StopCaptureForClient( ...@@ -299,6 +299,16 @@ void VideoCaptureManager::StopCaptureForClient(
NOTREACHED(); NOTREACHED();
return; return;
} }
if (aborted_due_to_error) {
SessionMap::iterator it;
for (it = sessions_.begin(); it != sessions_.end(); ++it) {
if (it->second.type == entry->stream_type &&
it->second.id == entry->id) {
listener_->Aborted(it->second.type, it->first);
break;
}
}
}
// Detach client from controller. // Detach client from controller.
media::VideoCaptureSessionId session_id = media::VideoCaptureSessionId session_id =
...@@ -316,8 +326,7 @@ bool VideoCaptureManager::GetDeviceSupportedFormats( ...@@ -316,8 +326,7 @@ bool VideoCaptureManager::GetDeviceSupportedFormats(
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(supported_formats->empty()); DCHECK(supported_formats->empty());
std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator it = SessionMap::iterator it = sessions_.find(capture_session_id);
sessions_.find(capture_session_id);
if (it == sessions_.end()) if (it == sessions_.end())
return false; return false;
DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name; DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name;
...@@ -336,8 +345,7 @@ bool VideoCaptureManager::GetDeviceFormatsInUse( ...@@ -336,8 +345,7 @@ bool VideoCaptureManager::GetDeviceFormatsInUse(
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(formats_in_use->empty()); DCHECK(formats_in_use->empty());
std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator it = SessionMap::iterator it = sessions_.find(capture_session_id);
sessions_.find(capture_session_id);
if (it == sessions_.end()) if (it == sessions_.end())
return false; return false;
DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name; DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name;
...@@ -357,8 +365,7 @@ void VideoCaptureManager::SetDesktopCaptureWindowId( ...@@ -357,8 +365,7 @@ void VideoCaptureManager::SetDesktopCaptureWindowId(
media::VideoCaptureSessionId session_id, media::VideoCaptureSessionId session_id,
gfx::NativeViewId window_id) { gfx::NativeViewId window_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator SessionMap::iterator session_it = sessions_.find(session_id);
session_it = sessions_.find(session_id);
if (session_it == sessions_.end()) { if (session_it == sessions_.end()) {
device_task_runner_->PostTask( device_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
...@@ -520,9 +527,9 @@ VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( ...@@ -520,9 +527,9 @@ VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
VideoCaptureManager::DeviceEntry* VideoCaptureManager::DeviceEntry*
VideoCaptureManager::GetDeviceEntryForController( VideoCaptureManager::GetDeviceEntryForController(
const VideoCaptureController* controller) { const VideoCaptureController* controller) const {
// Look up |controller| in |devices_|. // Look up |controller| in |devices_|.
for (DeviceEntries::iterator it = devices_.begin(); for (DeviceEntries::const_iterator it = devices_.begin();
it != devices_.end(); ++it) { it != devices_.end(); ++it) {
if ((*it)->video_capture_controller.get() == controller) { if ((*it)->video_capture_controller.get() == controller) {
return *it; return *it;
...@@ -555,8 +562,7 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( ...@@ -555,8 +562,7 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
media::VideoCaptureSessionId capture_session_id) { media::VideoCaptureSessionId capture_session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator SessionMap::iterator session_it = sessions_.find(capture_session_id);
session_it = sessions_.find(capture_session_id);
if (session_it == sessions_.end()) { if (session_it == sessions_.end()) {
return NULL; return NULL;
} }
......
...@@ -79,7 +79,8 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider { ...@@ -79,7 +79,8 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// function. // function.
void StopCaptureForClient(VideoCaptureController* controller, void StopCaptureForClient(VideoCaptureController* controller,
VideoCaptureControllerID client_id, VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler); VideoCaptureControllerEventHandler* client_handler,
bool aborted_due_to_error);
// Retrieves all capture supported formats for a particular device. Returns // Retrieves all capture supported formats for a particular device. Returns
// false if the |capture_session_id| is not found. The supported formats are // false if the |capture_session_id| is not found. The supported formats are
...@@ -147,7 +148,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider { ...@@ -147,7 +148,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// Find the DeviceEntry that owns a particular controller pointer. // Find the DeviceEntry that owns a particular controller pointer.
DeviceEntry* GetDeviceEntryForController( DeviceEntry* GetDeviceEntryForController(
const VideoCaptureController* controller); const VideoCaptureController* controller) const;
bool IsOnDeviceThread() const; bool IsOnDeviceThread() const;
...@@ -189,11 +190,12 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider { ...@@ -189,11 +190,12 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
MediaStreamProviderListener* listener_; MediaStreamProviderListener* listener_;
media::VideoCaptureSessionId new_capture_session_id_; media::VideoCaptureSessionId new_capture_session_id_;
typedef std::map<media::VideoCaptureSessionId, MediaStreamDevice> SessionMap;
// An entry is kept in this map for every session that has been created via // An entry is kept in this map for every session that has been created via
// the Open() entry point. The keys are session_id's. This map is used to // the Open() entry point. The keys are session_id's. This map is used to
// determine which device to use when StartCaptureForClient() occurs. Used // determine which device to use when StartCaptureForClient() occurs. Used
// only on the IO thread. // only on the IO thread.
std::map<media::VideoCaptureSessionId, MediaStreamDevice> sessions_; SessionMap sessions_;
// An entry, kept in a map, that owns a VideoCaptureDevice and its associated // An entry, kept in a map, that owns a VideoCaptureDevice and its associated
// VideoCaptureController. VideoCaptureManager owns all VideoCaptureDevices // VideoCaptureController. VideoCaptureManager owns all VideoCaptureDevices
......
...@@ -38,8 +38,7 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener { ...@@ -38,8 +38,7 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener {
MOCK_METHOD2(Closed, void(MediaStreamType, int)); MOCK_METHOD2(Closed, void(MediaStreamType, int));
MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType, MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType,
const StreamDeviceInfoArray&)); const StreamDeviceInfoArray&));
MOCK_METHOD3(Error, void(MediaStreamType, int, MOCK_METHOD2(Aborted, void(MediaStreamType, int));
MediaStreamProviderError));
}; // class MockMediaStreamProviderListener }; // class MockMediaStreamProviderListener
// Needed as an input argument to StartCaptureForClient(). // Needed as an input argument to StartCaptureForClient().
...@@ -131,7 +130,7 @@ class VideoCaptureManagerTest : public testing::Test { ...@@ -131,7 +130,7 @@ class VideoCaptureManagerTest : public testing::Test {
void StopClient(VideoCaptureControllerID client_id) { void StopClient(VideoCaptureControllerID client_id) {
ASSERT_TRUE(1 == controllers_.count(client_id)); ASSERT_TRUE(1 == controllers_.count(client_id));
vcm_->StopCaptureForClient(controllers_[client_id], client_id, vcm_->StopCaptureForClient(controllers_[client_id], client_id,
frame_observer_.get()); frame_observer_.get(), false);
controllers_.erase(client_id); controllers_.erase(client_id);
} }
...@@ -176,6 +175,35 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) { ...@@ -176,6 +175,35 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) {
vcm_->Unregister(); vcm_->Unregister();
} }
// Try to open, start, and abort a device.
TEST_F(VideoCaptureManagerTest, CreateAndAbort) {
StreamDeviceInfoArray devices;
InSequence s;
EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
.WillOnce(SaveArg<1>(&devices));
EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _));
EXPECT_CALL(*listener_, Aborted(MEDIA_DEVICE_VIDEO_CAPTURE, _));
vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
// Wait to get device callback.
message_loop_->RunUntilIdle();
int video_session_id = vcm_->Open(devices.front());
VideoCaptureControllerID client_id = StartClient(video_session_id, true);
// Wait for device opened.
message_loop_->RunUntilIdle();
vcm_->StopCaptureForClient(controllers_[client_id], client_id,
frame_observer_.get(), true);
// Wait to check callbacks before removing the listener.
message_loop_->RunUntilIdle();
vcm_->Unregister();
}
// Open the same device twice. // Open the same device twice.
TEST_F(VideoCaptureManagerTest, OpenTwice) { TEST_F(VideoCaptureManagerTest, OpenTwice) {
StreamDeviceInfoArray devices; StreamDeviceInfoArray devices;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment