summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorperkj@google.com <perkj@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-28 12:10:20 +0000
committerperkj@google.com <perkj@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-28 12:10:20 +0000
commit47126547f951dc36455dce1551e6f893fc30045a (patch)
treec03116e98e827f357e48a76e6202f011f3a30c5d /content
parent4bdba60a7f44c1659173d97f425c5d2e616daeb3 (diff)
downloadchromium_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.h1
-rw-r--r--content/common/media/media_stream_messages.h66
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/content_renderer.gypi3
-rw-r--r--content/renderer/media/media_stream_dispatcher.cc157
-rw-r--r--content/renderer/media/media_stream_dispatcher.h96
-rw-r--r--content/renderer/media/media_stream_dispatcher_eventhandler.h39
-rw-r--r--content/renderer/media/media_stream_dispatcher_unittest.cc201
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));
+}