diff options
author | perkj@google.com <perkj@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-28 12:10:20 +0000 |
---|---|---|
committer | perkj@google.com <perkj@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-28 12:10:20 +0000 |
commit | 47126547f951dc36455dce1551e6f893fc30045a (patch) | |
tree | c03116e98e827f357e48a76e6202f011f3a30c5d /content | |
parent | 4bdba60a7f44c1659173d97f425c5d2e616daeb3 (diff) | |
download | chromium_src-47126547f951dc36455dce1551e6f893fc30045a.zip chromium_src-47126547f951dc36455dce1551e6f893fc30045a.tar.gz chromium_src-47126547f951dc36455dce1551e6f893fc30045a.tar.bz2 |
MediaStreamDispatcher
This is the second Chromium patch needed to support media streams
http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#video-conferencing-and-peer-to-peer-communication. The first patch is here http://codereview.chromium.org/7192007/.
The patch contain types needed in both the render and browser process and MediaStreamDispatcher that is used for sending request from the render process to the browser process for granting a webpage access to audio input and video capture devices.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/7184010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90752 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/common/content_message_generator.h | 1 | ||||
-rw-r--r-- | content/common/media/media_stream_messages.h | 66 | ||||
-rw-r--r-- | content/content_common.gypi | 1 | ||||
-rw-r--r-- | content/content_renderer.gypi | 3 | ||||
-rw-r--r-- | content/renderer/media/media_stream_dispatcher.cc | 157 | ||||
-rw-r--r-- | content/renderer/media/media_stream_dispatcher.h | 96 | ||||
-rw-r--r-- | content/renderer/media/media_stream_dispatcher_eventhandler.h | 39 | ||||
-rw-r--r-- | content/renderer/media/media_stream_dispatcher_unittest.cc | 201 |
8 files changed, 564 insertions, 0 deletions
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h index 1df560f..618da95 100644 --- a/content/common/content_message_generator.h +++ b/content/common/content_message_generator.h @@ -23,6 +23,7 @@ #include "content/common/gpu/gpu_messages.h" #include "content/common/indexed_db_messages.h" #include "content/common/media/audio_messages.h" +#include "content/common/media/media_stream_messages.h" #include "content/common/media/video_capture_messages.h" #include "content/common/mime_registry_messages.h" #include "content/common/p2p_messages.h" diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h new file mode 100644 index 0000000..3f9d3df --- /dev/null +++ b/content/common/media/media_stream_messages.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// IPC messages for the media streaming. +// Multiply-included message file, hence no include guard. + +#include <string> + +#include "content/common/media/media_stream_options.h" +#include "ipc/ipc_message_macros.h" + +#define IPC_MESSAGE_START MediaStreamMsgStart + +IPC_ENUM_TRAITS(media_stream::MediaStreamType) +IPC_ENUM_TRAITS(media_stream::StreamOptions::VideoOption) + +IPC_STRUCT_TRAITS_BEGIN(media_stream::StreamOptions) + IPC_STRUCT_TRAITS_MEMBER(audio) + IPC_STRUCT_TRAITS_MEMBER(video_option) +IPC_STRUCT_TRAITS_END() + +IPC_STRUCT_TRAITS_BEGIN(media_stream::StreamDeviceInfo) + IPC_STRUCT_TRAITS_MEMBER(stream_type) + IPC_STRUCT_TRAITS_MEMBER(name) + IPC_STRUCT_TRAITS_MEMBER(device_id) + IPC_STRUCT_TRAITS_MEMBER(in_use) + IPC_STRUCT_TRAITS_MEMBER(session_id) +IPC_STRUCT_TRAITS_END() + +// Message sent from the browser to the renderer + +// The browser has generated a stream successfully. +IPC_MESSAGE_ROUTED4(MediaStreamMsg_StreamGenerated, + int /* request id */, + std::string /* label */, + media_stream::StreamDeviceInfoArray /* audio_device_list */, + media_stream::StreamDeviceInfoArray /* video_device_list */) + +// The browser has failed to generate a stream. +IPC_MESSAGE_ROUTED1(MediaStreamMsg_StreamGenerationFailed, + int /* request id */) + +// Report of a failure of a video device. +IPC_MESSAGE_ROUTED2(MediaStreamHostMsg_VideoDeviceFailed, + std::string /* label */, + int /* index */) + +// Report of a failure of an audio device. +IPC_MESSAGE_ROUTED2(MediaStreamHostMsg_AudioDeviceFailed, + std::string /* label */, + int /* index */) + +// Messages sent from the renderer to the browser. + +// Request a new media stream. +IPC_MESSAGE_CONTROL4(MediaStreamHostMsg_GenerateStream, + int /* render view id */, + int /* request id */, + media_stream::StreamOptions /* options */, + std::string /* security origin */) + +// Request to stop streaming from the media stream. +IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_StopGeneratedStream, + int /* render view id */, + std::string /* label */) diff --git a/content/content_common.gypi b/content/content_common.gypi index 48e6636..8fcc25a 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -144,6 +144,7 @@ 'common/main_function_params.h', 'common/media/audio_messages.h', 'common/media/audio_stream_state.h', + 'common/media/media_stream_messages.h', 'common/media/media_stream_options.cc', 'common/media/media_stream_options.h', 'common/media/video_capture_messages.h', diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 595694a..23b5ecd 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -66,6 +66,9 @@ 'renderer/media/audio_message_filter.h', 'renderer/media/audio_renderer_impl.cc', 'renderer/media/audio_renderer_impl.h', + 'renderer/media/media_stream_dispatcher.cc', + 'renderer/media/media_stream_dispatcher.h', + 'renderer/media/media_stream_dispatcher_eventhandler.h', 'renderer/media/video_capture_impl.cc', 'renderer/media/video_capture_impl.h', 'renderer/media/video_capture_impl_manager.cc', diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc new file mode 100644 index 0000000..7482ac2 --- /dev/null +++ b/content/renderer/media/media_stream_dispatcher.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/media_stream_dispatcher.h" + +#include "base/logging.h" +#include "content/common/media/media_stream_messages.h" +#include "content/renderer/media/media_stream_dispatcher_eventhandler.h" + +MediaStreamDispatcherEventHandler::~MediaStreamDispatcherEventHandler() {} + +MediaStreamDispatcher::MediaStreamDispatcher(RenderView* render_view) + : RenderViewObserver(render_view), + next_ipc_id_(0) { +} + +MediaStreamDispatcher::~MediaStreamDispatcher() {} + +void MediaStreamDispatcher::GenerateStream( + int request_id, + MediaStreamDispatcherEventHandler* event_handler, + media_stream::StreamOptions components, + const std::string& security_origin) { + VLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")"; + + requests_.push_back(Request(event_handler, request_id, next_ipc_id_)); + Send(new MediaStreamHostMsg_GenerateStream(routing_id(), + next_ipc_id_++, + components, + security_origin)); +} + +void MediaStreamDispatcher::StopStream(const std::string& label) { + VLOG(1) << "MediaStreamDispatcher::StopStream" + << ", {label = " << label << "}"; + + LabelStreamMap::iterator it = label_stream_map_.find(label); + if (it == label_stream_map_.end()) + return; + + Send(new MediaStreamHostMsg_StopGeneratedStream(routing_id(), label)); + label_stream_map_.erase(it); +} + +bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcher, message) + IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, + OnStreamGenerated) + IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed, + OnStreamGenerationFailed) + IPC_MESSAGE_HANDLER(MediaStreamHostMsg_VideoDeviceFailed, + OnVideoDeviceFailed) + IPC_MESSAGE_HANDLER(MediaStreamHostMsg_AudioDeviceFailed, + OnAudioDeviceFailed) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void MediaStreamDispatcher::OnStreamGenerated( + int request_id, + const std::string& label, + const media_stream::StreamDeviceInfoArray& audio_array, + const media_stream::StreamDeviceInfoArray& video_array) { + + for (RequestList::iterator it = requests_.begin(); + it != requests_.end(); ++it) { + Request& request = *it; + if (request.ipc_request == request_id) { + Stream new_stream; + new_stream.handler = request.handler; + new_stream.audio_array = audio_array; + new_stream.video_array = video_array; + label_stream_map_[label] = new_stream; + request.handler->OnStreamGenerated(request.request_id, label, + audio_array, video_array); + VLOG(1) << "MediaStreamDispatcher::OnStreamGenerated(" + << request.request_id << ", " << label << ")"; + requests_.erase(it); + break; + } + } +} + +void MediaStreamDispatcher::OnStreamGenerationFailed(int request_id) { + for (RequestList::iterator it = requests_.begin(); + it != requests_.end(); ++it) { + Request& request = *it; + if (request.ipc_request == request_id) { + request.handler->OnStreamGenerationFailed(request.request_id); + VLOG(1) << "MediaStreamDispatcher::OnStreamGenerationFailed(" + << request.request_id << ")\n"; + requests_.erase(it); + break; + } + } +} + +void MediaStreamDispatcher::OnVideoDeviceFailed(const std::string& label, + int index) { + LabelStreamMap::iterator it = label_stream_map_.find(label); + if (it == label_stream_map_.end()) + return; + + // index is the index in the video_array that has failed. + DCHECK_GT(it->second.video_array.size(), static_cast<size_t>(index)); + media_stream::StreamDeviceInfoArray::iterator device_it = + it->second.video_array.begin(); + it->second.video_array.erase(device_it + index); + it->second.handler->OnVideoDeviceFailed(label, index); +} + +void MediaStreamDispatcher::OnAudioDeviceFailed(const std::string& label, + int index) { + LabelStreamMap::iterator it = label_stream_map_.find(label); + if (it == label_stream_map_.end()) + return; + + // index is the index in the audio_array that has failed. + DCHECK_GT(it->second.audio_array.size(), static_cast<size_t>(index)); + media_stream::StreamDeviceInfoArray::iterator device_it = + it->second.audio_array.begin(); + it->second.audio_array.erase(device_it + index); + it->second.handler->OnAudioDeviceFailed(label, index); +} + +int MediaStreamDispatcher::audio_session_id(const std::string& label, + int index) { + LabelStreamMap::iterator it = label_stream_map_.find(label); + if (it == label_stream_map_.end()) + return media_stream::StreamDeviceInfo::kNoId; + + DCHECK_GT(it->second.audio_array.size(), static_cast<size_t>(index)); + return it->second.audio_array[index].session_id; +} + +bool MediaStreamDispatcher::IsStream(const std::string& label) { + return label_stream_map_.find(label) != label_stream_map_.end(); +} + +int MediaStreamDispatcher::video_session_id(const std::string& label, + int index) { + LabelStreamMap::iterator it = label_stream_map_.find(label); + if (it == label_stream_map_.end()) + return media_stream::StreamDeviceInfo::kNoId; + + DCHECK_GT(it->second.video_array.size(), static_cast<size_t>(index)); + return it->second.video_array[index].session_id; +} + +MediaStreamDispatcher::Stream::Stream() + : handler(NULL) {} + +MediaStreamDispatcher::Stream::~Stream() {} + diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h new file mode 100644 index 0000000..d154c8b --- /dev/null +++ b/content/renderer/media/media_stream_dispatcher.h @@ -0,0 +1,96 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_H_ + +#include <list> +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "base/message_loop.h" +#include "content/common/media/media_stream_options.h" +#include "content/renderer/media/media_stream_dispatcher_eventhandler.h" +#include "content/renderer/render_view_observer.h" + +// MediaStreamDispatcher is a delegate for the Media Stream API messages. +// MediaStreams are used by WebKit to open media devices such as Video Capture +// and Audio input devices. +// It's the complement of MediaStreamDispatcherHost (owned by +// BrowserRenderProcessHost). +class MediaStreamDispatcher : public RenderViewObserver { + public: + explicit MediaStreamDispatcher(RenderView* render_view); + virtual ~MediaStreamDispatcher(); + + // Request a new media stream to be created. + // This can be used either of WebKit or a plugin. + // Note: The event_handler must be valid for as long as the stream exists. + void GenerateStream(int request_id, + MediaStreamDispatcherEventHandler* event_handler, + media_stream::StreamOptions components, + const std::string& security_origin); + + // Stop a started stream. Label is the label provided in OnStreamGenerated. + void StopStream(const std::string& label); + + // Check if the label is a valid stream. + bool IsStream(const std::string& label); + // Get the video session_id given a label. The label identifies a stream. + // index is the index in the video_device_array of the stream. + int video_session_id(const std::string& label, int index); + // Returns an audio session_id given a label and an index. + int audio_session_id(const std::string& label, int index); + + private: + FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, Basic); + FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, TestFailure); + + struct Request { + Request(MediaStreamDispatcherEventHandler* handler, + int request_id, + int ipc_request) + : handler(handler), + request_id(request_id), + ipc_request(ipc_request) { + } + MediaStreamDispatcherEventHandler* handler; + int request_id; + int ipc_request; + }; + + // Private class for keeping track of opened devices and who have + // opened it. + struct Stream { + Stream(); + ~Stream(); + MediaStreamDispatcherEventHandler* handler; + media_stream::StreamDeviceInfoArray audio_array; + media_stream::StreamDeviceInfoArray video_array; + }; + + // Messages from the browser. + virtual bool OnMessageReceived(const IPC::Message& message); + void OnStreamGenerated( + int request_id, + const std::string& label, + const media_stream::StreamDeviceInfoArray& audio_array, + const media_stream::StreamDeviceInfoArray& video_array); + void OnStreamGenerationFailed(int request_id); + void OnVideoDeviceFailed(const std::string& label, int index); + void OnAudioDeviceFailed(const std::string& label, int index); + + int next_ipc_id_; + typedef std::map<std::string, Stream> LabelStreamMap; + LabelStreamMap label_stream_map_; + + // List of calls made to GenerateStream that has not yet completed. + typedef std::list<Request> RequestList; + RequestList requests_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamDispatcher); +}; + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_H_ diff --git a/content/renderer/media/media_stream_dispatcher_eventhandler.h b/content/renderer/media/media_stream_dispatcher_eventhandler.h new file mode 100644 index 0000000..4388eea --- /dev/null +++ b/content/renderer/media/media_stream_dispatcher_eventhandler.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_EVENTHANDLER_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_EVENTHANDLER_H_ + +#include <string> + +#include "content/common/media/media_stream_options.h" + +class MediaStreamDispatcherEventHandler { + public: + // A new media stream have been created. + virtual void OnStreamGenerated( + int request_id, + const std::string& label, + const media_stream::StreamDeviceInfoArray& audio_device_array, + const media_stream::StreamDeviceInfoArray& video_device_array) = 0; + + // Creation of a new media stream failed. The user might have denied access + // to the requested devices or no device is available. + virtual void OnStreamGenerationFailed(int request_id) = 0; + + // An error have occurred on a video device. This is called if a runtime + // error occurs. + virtual void OnVideoDeviceFailed(const std::string& label, + int index) = 0; + + // An error have occurred on an audio device. This is called if a runtime + // error occurs. + virtual void OnAudioDeviceFailed(const std::string& label, + int index) = 0; + + protected: + virtual ~MediaStreamDispatcherEventHandler(); +}; + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DISPATCHER_EVENTHANDLER_H_ diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc new file mode 100644 index 0000000..c765d81 --- /dev/null +++ b/content/renderer/media/media_stream_dispatcher_unittest.cc @@ -0,0 +1,201 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "content/common/media/media_stream_messages.h" +#include "content/renderer/media/media_stream_dispatcher.h" +#include "content/renderer/media/media_stream_dispatcher_eventhandler.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const int kRouteId = 0; +const int kAudioSessionId = 3; +const int kVideoSessionId = 5; +const int kRequestId1 = 10; +const int kRequestId2 = 20; + +class MockMediaStreamDispatcherEventHandler + : public MediaStreamDispatcherEventHandler { + public: + MockMediaStreamDispatcherEventHandler() + : request_id_(-1), + audio_failed(false), + video_failed(false) {} + + virtual void OnStreamGenerated( + int request_id, + const std::string &label, + const media_stream::StreamDeviceInfoArray& audio_device_array, + const media_stream::StreamDeviceInfoArray& video_device_array) { + request_id_ = request_id; + label_ = label; + } + + virtual void OnStreamGenerationFailed(int request_id) { + request_id_ = request_id; + } + + virtual void OnAudioDeviceFailed(const std::string& label, + int index) { + audio_failed = true; + } + + virtual void OnVideoDeviceFailed(const std::string& label, + int index) { + video_failed = true; + } + + int request_id_; + std::string label_; + bool audio_failed; + bool video_failed; + + DISALLOW_COPY_AND_ASSIGN(MockMediaStreamDispatcherEventHandler); +}; + +} // namespace + +TEST(MediaStreamDispatcherTest, Basic) { + scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); + scoped_ptr<MockMediaStreamDispatcherEventHandler> + handler(new MockMediaStreamDispatcherEventHandler); + media_stream::StreamOptions components( + true, media_stream::StreamOptions::kFacingUser); + std::string security_origin; + + int ipc_request_id1 = dispatcher->next_ipc_id_; + dispatcher->GenerateStream(kRequestId1, handler.get(), components, + security_origin); + int ipc_request_id2 = dispatcher->next_ipc_id_; + EXPECT_NE(ipc_request_id1, ipc_request_id2); + dispatcher->GenerateStream(kRequestId2, handler.get(), components, + security_origin); + EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); + + media_stream::StreamDeviceInfoArray audio_device_array(1); + media_stream::StreamDeviceInfo audio_device_info; + audio_device_info.name = "Microphone"; + audio_device_info.stream_type = media_stream::kAudioCapture; + audio_device_info.session_id = kAudioSessionId; + audio_device_array[0] = audio_device_info; + + media_stream::StreamDeviceInfoArray video_device_array(1); + media_stream::StreamDeviceInfo video_device_info; + video_device_info.name = "Camera"; + video_device_info.stream_type = media_stream::kVideoCapture; + video_device_info.session_id = kVideoSessionId; + video_device_array[0] = video_device_info; + + // Complete the creation of stream1. + std::string stream_label1 = std::string("stream1"); + dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( + kRouteId, ipc_request_id1, stream_label1, + audio_device_array, video_device_array)); + EXPECT_EQ(handler->request_id_, kRequestId1); + EXPECT_EQ(handler->label_, stream_label1); + + // Complete the creation of stream2. + std::string stream_label2 = std::string("stream2"); + dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( + kRouteId, ipc_request_id2, stream_label2, + audio_device_array, video_device_array)); + EXPECT_EQ(handler->request_id_, kRequestId2); + EXPECT_EQ(handler->label_, stream_label2); + + EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); + EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2)); + + // Check the session_id of stream2. + EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0), kAudioSessionId); + EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId); + + // Stop stream2. + dispatcher->StopStream(stream_label2); + EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0), + media_stream::StreamDeviceInfo::kNoId); + EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), + media_stream::StreamDeviceInfo::kNoId); + + // Stop stream1. + dispatcher->StopStream(stream_label1); + EXPECT_EQ(dispatcher->audio_session_id(stream_label1, 0), + media_stream::StreamDeviceInfo::kNoId); + EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), + media_stream::StreamDeviceInfo::kNoId); + EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); + + // Verify that the request have been completed. + EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); + EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); +} + +TEST(MediaStreamDispatcherTest, TestFailure) { + scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); + scoped_ptr<MockMediaStreamDispatcherEventHandler> + handler(new MockMediaStreamDispatcherEventHandler); + media_stream::StreamOptions components( + true, media_stream::StreamOptions::kFacingUser); + std::string security_origin; + + // Test failure when creating a stream. + int ipc_request_id1 = dispatcher->next_ipc_id_; + dispatcher->GenerateStream(kRequestId1, handler.get(), components, + security_origin); + dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerationFailed( + kRouteId, ipc_request_id1)); + + // Verify that the request have been completed. + EXPECT_EQ(handler->request_id_, kRequestId1); + EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); + + // Create a new stream. + ipc_request_id1 = dispatcher->next_ipc_id_; + dispatcher->GenerateStream(kRequestId1, handler.get(), components, + security_origin); + + media_stream::StreamDeviceInfoArray audio_device_array(1); + media_stream::StreamDeviceInfo audio_device_info; + audio_device_info.name = "Microphone"; + audio_device_info.stream_type = media_stream::kAudioCapture; + audio_device_info.session_id = kAudioSessionId; + audio_device_array[0] = audio_device_info; + + media_stream::StreamDeviceInfoArray video_device_array(1); + media_stream::StreamDeviceInfo video_device_info; + video_device_info.name = "Camera"; + video_device_info.stream_type = media_stream::kVideoCapture; + video_device_info.session_id = kVideoSessionId; + video_device_array[0] = video_device_info; + + // Complete the creation of stream1. + std::string stream_label1 = std::string("stream1"); + dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( + kRouteId, ipc_request_id1, stream_label1, + audio_device_array, video_device_array)); + EXPECT_EQ(handler->request_id_, kRequestId1); + EXPECT_EQ(handler->label_, stream_label1); + EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId); + + // Test failure of the video device. + dispatcher->OnMessageReceived( + MediaStreamHostMsg_VideoDeviceFailed(kRouteId, stream_label1, 0)); + EXPECT_EQ(handler->video_failed, true); + EXPECT_EQ(handler->audio_failed, false); + // Make sure the audio device still exist but not the video device. + EXPECT_EQ(dispatcher->audio_session_id(stream_label1, 0), kAudioSessionId); + + // Test failure of the audio device. + dispatcher->OnMessageReceived( + MediaStreamHostMsg_AudioDeviceFailed(kRouteId, stream_label1, 0)); + EXPECT_EQ(handler->audio_failed, true); + + // Stop stream1. + dispatcher->StopStream(stream_label1); + EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); +} |