Commit ab09b819 authored by Chandan Padhi's avatar Chandan Padhi Committed by Commit Bot

Migrate MediaStream IPC messages to Mojo - part 5

This CL migrates all the remaining browser to renderer IPC messages.

Bug: 742682
Change-Id: I968d9c2f4898dd293fcb6941c746e1d20473f81f
Reviewed-on: https://chromium-review.googlesource.com/596107Reviewed-by: default avatarEmircan Uysaler <emircan@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Commit-Queue: Chandan Padhi <c.padhi@samsung.com>
Cr-Commit-Position: refs/heads/master@{#491908}
parent 37af16a9
...@@ -53,8 +53,22 @@ void MediaStreamDispatcherHost::StreamGenerated( ...@@ -53,8 +53,22 @@ void MediaStreamDispatcherHost::StreamGenerated(
DVLOG(1) << __func__ << " label= " << label; DVLOG(1) << __func__ << " label= " << label;
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
Send(new MediaStreamMsg_StreamGenerated( auto it = dispatchers_.find(render_frame_id);
render_frame_id, page_request_id, label, audio_devices, video_devices)); if (it != dispatchers_.end()) {
it->second->OnStreamGenerated(page_request_id, label, audio_devices,
video_devices);
return;
}
// TODO(c.padhi): Avoid this hop between threads if possible, see
// https://crbug.com/742682.
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, FROM_HERE,
base::Bind(&GetMediaStreamDispatcherPtrInfo, render_process_id_,
render_frame_id),
base::Bind(&MediaStreamDispatcherHost::OnStreamGenerated,
base::Unretained(this), render_frame_id, page_request_id,
label, audio_devices, video_devices));
} }
void MediaStreamDispatcherHost::StreamGenerationFailed( void MediaStreamDispatcherHost::StreamGenerationFailed(
...@@ -89,7 +103,20 @@ void MediaStreamDispatcherHost::DeviceStopped(int render_frame_id, ...@@ -89,7 +103,20 @@ void MediaStreamDispatcherHost::DeviceStopped(int render_frame_id,
<< " device_id=" << device.device.id; << " device_id=" << device.device.id;
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
Send(new MediaStreamMsg_DeviceStopped(render_frame_id, label, device)); auto it = dispatchers_.find(render_frame_id);
if (it != dispatchers_.end()) {
it->second->OnDeviceStopped(label, device);
return;
}
// TODO(c.padhi): Avoid this hop between threads if possible, see
// https://crbug.com/742682.
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, FROM_HERE,
base::Bind(&GetMediaStreamDispatcherPtrInfo, render_process_id_,
render_frame_id),
base::Bind(&MediaStreamDispatcherHost::OnDeviceStopped,
base::Unretained(this), render_frame_id, label, device));
} }
void MediaStreamDispatcherHost::DeviceOpened( void MediaStreamDispatcherHost::DeviceOpened(
...@@ -100,8 +127,21 @@ void MediaStreamDispatcherHost::DeviceOpened( ...@@ -100,8 +127,21 @@ void MediaStreamDispatcherHost::DeviceOpened(
DVLOG(1) << __func__ << " page_request_id=" << page_request_id; DVLOG(1) << __func__ << " page_request_id=" << page_request_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
Send(new MediaStreamMsg_DeviceOpened( auto it = dispatchers_.find(render_frame_id);
render_frame_id, page_request_id, label, video_device)); if (it != dispatchers_.end()) {
it->second->OnDeviceOpened(page_request_id, label, video_device);
return;
}
// TODO(c.padhi): Avoid this hop between threads if possible, see
// https://crbug.com/742682.
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, FROM_HERE,
base::Bind(&GetMediaStreamDispatcherPtrInfo, render_process_id_,
render_frame_id),
base::Bind(&MediaStreamDispatcherHost::OnDeviceOpened,
base::Unretained(this), render_frame_id, page_request_id,
label, video_device));
} }
bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) { bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) {
...@@ -233,6 +273,23 @@ void MediaStreamDispatcherHost::StreamStarted(const std::string& label) { ...@@ -233,6 +273,23 @@ void MediaStreamDispatcherHost::StreamStarted(const std::string& label) {
media_stream_manager_->OnStreamStarted(label); media_stream_manager_->OnStreamStarted(label);
} }
void MediaStreamDispatcherHost::OnStreamGenerated(
int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
mojom::MediaStreamDispatcherPtr dispatcher =
mojo::MakeProxy(std::move(dispatcher_info));
DCHECK(dispatcher.is_bound());
dispatcher->OnStreamGenerated(page_request_id, label, audio_devices,
video_devices);
dispatchers_[render_frame_id] = std::move(dispatcher);
}
void MediaStreamDispatcherHost::OnStreamGenerationFailed( void MediaStreamDispatcherHost::OnStreamGenerationFailed(
int render_frame_id, int render_frame_id,
int page_request_id, int page_request_id,
...@@ -247,6 +304,21 @@ void MediaStreamDispatcherHost::OnStreamGenerationFailed( ...@@ -247,6 +304,21 @@ void MediaStreamDispatcherHost::OnStreamGenerationFailed(
dispatchers_[render_frame_id] = std::move(dispatcher); dispatchers_[render_frame_id] = std::move(dispatcher);
} }
void MediaStreamDispatcherHost::OnDeviceOpened(
int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& video_device,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
mojom::MediaStreamDispatcherPtr dispatcher =
mojo::MakeProxy(std::move(dispatcher_info));
DCHECK(dispatcher.is_bound());
dispatcher->OnDeviceOpened(page_request_id, label, video_device);
dispatchers_[render_frame_id] = std::move(dispatcher);
}
void MediaStreamDispatcherHost::OnDeviceOpenFailed( void MediaStreamDispatcherHost::OnDeviceOpenFailed(
int render_frame_id, int render_frame_id,
int page_request_id, int page_request_id,
...@@ -260,4 +332,18 @@ void MediaStreamDispatcherHost::OnDeviceOpenFailed( ...@@ -260,4 +332,18 @@ void MediaStreamDispatcherHost::OnDeviceOpenFailed(
dispatchers_[render_frame_id] = std::move(dispatcher); dispatchers_[render_frame_id] = std::move(dispatcher);
} }
void MediaStreamDispatcherHost::OnDeviceStopped(
int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
mojom::MediaStreamDispatcherPtr dispatcher =
mojo::MakeProxy(std::move(dispatcher_info));
DCHECK(dispatcher.is_bound());
dispatcher->OnDeviceStopped(label, device);
dispatchers_[render_frame_id] = std::move(dispatcher);
}
} // namespace content } // namespace content
...@@ -93,14 +93,29 @@ class CONTENT_EXPORT MediaStreamDispatcherHost ...@@ -93,14 +93,29 @@ class CONTENT_EXPORT MediaStreamDispatcherHost
bool is_secure) override; bool is_secure) override;
void StreamStarted(const std::string& label) override; void StreamStarted(const std::string& label) override;
void OnStreamGenerated(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info);
void OnStreamGenerationFailed( void OnStreamGenerationFailed(
int render_frame_id, int render_frame_id,
int page_request_id, int page_request_id,
MediaStreamRequestResult result, MediaStreamRequestResult result,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info); mojom::MediaStreamDispatcherPtrInfo dispatcher_info);
void OnDeviceOpened(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& video_device,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info);
void OnDeviceOpenFailed(int render_frame_id, void OnDeviceOpenFailed(int render_frame_id,
int page_request_id, int page_request_id,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info); mojom::MediaStreamDispatcherPtrInfo dispatcher_info);
void OnDeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device,
mojom::MediaStreamDispatcherPtrInfo dispatcher_info);
std::map<int, mojom::MediaStreamDispatcherPtr> dispatchers_; std::map<int, mojom::MediaStreamDispatcherPtr> dispatchers_;
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "media/audio/test_audio_thread.h" #include "media/audio/test_audio_thread.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/capture/video/fake_video_capture_device_factory.h" #include "media/capture/video/fake_video_capture_device_factory.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -95,18 +96,16 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -95,18 +96,16 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
MediaStreamManager* manager) MediaStreamManager* manager)
: MediaStreamDispatcherHost(kProcessId, salt, manager), : MediaStreamDispatcherHost(kProcessId, salt, manager),
binding_(this), task_runner_(task_runner) {}
task_runner_(task_runner),
current_ipc_(NULL) {}
// A list of mock methods. // A list of mock methods.
MOCK_METHOD4(OnStreamGenerated, MOCK_METHOD3(OnStreamGenerationSuccess,
void(int routing_id, int request_id, int audio_array_size, void(int request_id,
int audio_array_size,
int video_array_size)); int video_array_size));
MOCK_METHOD2(OnStreamGenerationFailure, MOCK_METHOD2(OnStreamGenerationFailure,
void(int request_id, MediaStreamRequestResult result)); void(int request_id, MediaStreamRequestResult result));
MOCK_METHOD1(OnDeviceStopped, void(int routing_id)); MOCK_METHOD0(OnDeviceStopSuccess, void());
MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id));
// Accessor to private functions. // Accessor to private functions.
void OnGenerateStream(int render_frame_id, void OnGenerateStream(int render_frame_id,
...@@ -140,16 +139,34 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -140,16 +139,34 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
} }
// mojom::MediaStreamDispatcher implementation. // mojom::MediaStreamDispatcher implementation.
void OnStreamGenerated(int32_t request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) override {
OnStreamGeneratedInternal(request_id, label, audio_array, video_array);
}
void OnStreamGenerationFailed(int32_t request_id, void OnStreamGenerationFailed(int32_t request_id,
MediaStreamRequestResult result) override { MediaStreamRequestResult result) override {
OnStreamGenerationFailedInternal(request_id, result); OnStreamGenerationFailedInternal(request_id, result);
} }
void OnDeviceOpened(int32_t request_id,
const std::string& label,
const StreamDeviceInfo& device_info) override {
OnDeviceOpenedInternal(request_id, label, device_info);
}
void OnDeviceOpenFailed(int32_t request_id) override {} void OnDeviceOpenFailed(int32_t request_id) override {}
void OnDeviceStopped(const std::string& label,
const StreamDeviceInfo& device_info) override {
OnDeviceStoppedInternal(label, device_info);
}
mojom::MediaStreamDispatcherPtr CreateInterfacePtrAndBind() { mojom::MediaStreamDispatcherPtr CreateInterfacePtrAndBind() {
mojom::MediaStreamDispatcherPtr dispatcher; mojom::MediaStreamDispatcherPtr dispatcher;
binding_.Bind(mojo::MakeRequest(&dispatcher)); bindings_.AddBinding(this, mojo::MakeRequest(&dispatcher));
return dispatcher; return dispatcher;
} }
...@@ -161,38 +178,14 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -161,38 +178,14 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
private: private:
~MockMediaStreamDispatcherHost() override {} ~MockMediaStreamDispatcherHost() override {}
// This method is used to dispatch IPC messages to the renderer. We intercept
// these messages here and dispatch to our mock methods to verify the
// conversation between this object and the renderer.
bool Send(IPC::Message* message) override {
CHECK(message);
current_ipc_ = message;
// In this method we dispatch the messages to the corresponding handlers as
// if we are the renderer.
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated,
OnStreamGeneratedInternal)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStoppedInternal)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpenedInternal)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
delete message;
current_ipc_ = NULL;
return true;
}
// These handler methods do minimal things and delegate to the mock methods. // These handler methods do minimal things and delegate to the mock methods.
void OnStreamGeneratedInternal( void OnStreamGeneratedInternal(
int request_id, int request_id,
std::string label, std::string label,
StreamDeviceInfoArray audio_device_list, StreamDeviceInfoArray audio_device_list,
StreamDeviceInfoArray video_device_list) { StreamDeviceInfoArray video_device_list) {
OnStreamGenerated(current_ipc_->routing_id(), request_id, OnStreamGenerationSuccess(request_id, audio_device_list.size(),
audio_device_list.size(), video_device_list.size()); video_device_list.size());
// Simulate the stream started event back to host for UI testing. // Simulate the stream started event back to host for UI testing.
OnStreamStarted(label); OnStreamStarted(label);
...@@ -225,7 +218,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -225,7 +218,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
if (IsAudioInputMediaType(device.device.type)) if (IsAudioInputMediaType(device.device.type))
EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0])); EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0]));
OnDeviceStopped(current_ipc_->routing_id()); OnDeviceStopSuccess();
} }
void OnDeviceOpenedInternal(int request_id, void OnDeviceOpenedInternal(int request_id,
...@@ -238,9 +231,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -238,9 +231,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
opened_device_ = device; opened_device_ = device;
} }
mojo::Binding<mojom::MediaStreamDispatcher> binding_; mojo::BindingSet<mojom::MediaStreamDispatcher> bindings_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
IPC::Message* current_ipc_;
std::queue<base::Closure> quit_closures_; std::queue<base::Closure> quit_closures_;
}; };
...@@ -359,10 +351,9 @@ class MediaStreamDispatcherHostTest : public testing::Test { ...@@ -359,10 +351,9 @@ class MediaStreamDispatcherHostTest : public testing::Test {
: 0; : 0;
int expected_video_array_size = int expected_video_array_size =
(controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0; (controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0;
EXPECT_CALL(*host_.get(), OnStreamGenerated(render_frame_id, EXPECT_CALL(*host_.get(), OnStreamGenerationSuccess(
page_request_id, page_request_id, expected_audio_array_size,
expected_audio_array_size, expected_video_array_size));
expected_video_array_size));
host_->OnGenerateStream(render_frame_id, page_request_id, controls, origin_, host_->OnGenerateStream(render_frame_id, page_request_id, controls, origin_,
run_loop.QuitClosure()); run_loop.QuitClosure());
run_loop.Run(); run_loop.Run();
...@@ -622,6 +613,10 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { ...@@ -622,6 +613,10 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
const int session_id1 = host_->video_devices_.front().session_id; const int session_id1 = host_->video_devices_.front().session_id;
// Generate second stream from another render frame. // Generate second stream from another render frame.
mojom::MediaStreamDispatcherPtr dispatcher =
host_->CreateInterfacePtrAndBind();
host_->SetMediaStreamDispatcherForTesting(kRenderId + 1,
std::move(dispatcher));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kRenderId + 1, kPageRequestId + 1, controls); GenerateStreamAndWaitForResult(kRenderId + 1, kPageRequestId + 1, controls);
...@@ -646,12 +641,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) { ...@@ -646,12 +641,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) {
SetupFakeUI(true); SetupFakeUI(true);
{ {
InSequence s; InSequence s;
EXPECT_CALL(*host_.get(), EXPECT_CALL(*host_.get(), OnStreamGenerationSuccess(kPageRequestId, 0, 1));
OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
// Generate second stream. // Generate second stream.
EXPECT_CALL(*host_.get(), EXPECT_CALL(*host_.get(),
OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1));
} }
base::RunLoop run_loop1; base::RunLoop run_loop1;
base::RunLoop run_loop2; base::RunLoop run_loop2;
...@@ -796,7 +790,7 @@ TEST_F(MediaStreamDispatcherHostTest, ...@@ -796,7 +790,7 @@ TEST_F(MediaStreamDispatcherHostTest,
// Generate a second stream. // Generate a second stream.
EXPECT_CALL(*host_.get(), EXPECT_CALL(*host_.get(),
OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1));
base::RunLoop run_loop1; base::RunLoop run_loop1;
host_->OnGenerateStream(kRenderId, kPageRequestId + 1, controls, origin_, host_->OnGenerateStream(kRenderId, kPageRequestId + 1, controls, origin_,
...@@ -857,7 +851,7 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { ...@@ -857,7 +851,7 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
EXPECT_EQ(host_->video_devices_.size(), 1u); EXPECT_EQ(host_->video_devices_.size(), 1u);
ASSERT_FALSE(close_callback.is_null()); ASSERT_FALSE(close_callback.is_null());
EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)); EXPECT_CALL(*host_.get(), OnDeviceStopSuccess());
close_callback.Run(); close_callback.Run();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
...@@ -874,7 +868,7 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) { ...@@ -874,7 +868,7 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
stub_video_device_ids_.clear(); stub_video_device_ids_.clear();
base::RunLoop run_loop; base::RunLoop run_loop;
EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)) EXPECT_CALL(*host_.get(), OnDeviceStopSuccess())
.WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
media_stream_manager_->media_devices_manager()->OnDevicesChanged( media_stream_manager_->media_devices_manager()->OnDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
......
...@@ -6,6 +6,13 @@ module content.mojom; ...@@ -6,6 +6,13 @@ module content.mojom;
import "url/mojo/origin.mojom"; import "url/mojo/origin.mojom";
// TODO(c.padhi): Add typemapping for StreamDeviceInfo,
// see https://crbug.com/742682.
// Native struct content::StreamDeviceInfo.
// (see content/common/media/media_stream_options.h)
[Native]
struct StreamDeviceInfo;
// Types of media streams (see content/public/common/media_stream_request.h). // Types of media streams (see content/public/common/media_stream_request.h).
enum MediaStreamType { enum MediaStreamType {
MEDIA_NO_SERVICE, MEDIA_NO_SERVICE,
...@@ -51,17 +58,32 @@ struct StreamControls { ...@@ -51,17 +58,32 @@ struct StreamControls {
bool disable_local_echo; bool disable_local_echo;
}; };
// Per-frame renderer-side interface that is used by the browser process to
// respond to media stream requests from the renderer.
interface MediaStreamDispatcher { interface MediaStreamDispatcher {
// TODO(c.padhi): Migrate the rest of the browser-to-renderer messages, // Informs the renderer that browser has generated a stream successfully.
// see https://crbug.com/742682. OnStreamGenerated(int32 request_id, string label,
array<StreamDeviceInfo> audio_array,
array<StreamDeviceInfo> video_array);
// Informs the renderer that browser has failed to generate a stream. // Informs the renderer that browser has failed to generate a stream.
OnStreamGenerationFailed(int32 request_id, MediaStreamRequestResult result); OnStreamGenerationFailed(int32 request_id, MediaStreamRequestResult result);
// TODO(wjia): should DeviceOpen* methods be merged with
// StreamGenerat* ones?
// Informs the renderer that browser has opened a device successfully.
OnDeviceOpened(int32 request_id, string label, StreamDeviceInfo device_info);
// Informs the renderer that browser has failed to open a device. // Informs the renderer that browser has failed to open a device.
OnDeviceOpenFailed(int32 request_id); OnDeviceOpenFailed(int32 request_id);
// The browser reports that a media device has been stopped. Stopping was
// triggered from the browser process.
OnDeviceStopped(string label, StreamDeviceInfo device_info);
}; };
// Per-process browser-side interface that is used by the renderer process to
// make media stream requests.
interface MediaStreamDispatcherHost { interface MediaStreamDispatcherHost {
// Requests a new media stream. // Requests a new media stream.
GenerateStream(int32 render_frame_id, int32 request_id, GenerateStream(int32 render_frame_id, int32 request_id,
......
...@@ -9,7 +9,10 @@ public_headers = [ ...@@ -9,7 +9,10 @@ public_headers = [
"//content/public/common/media_stream_request.h", "//content/public/common/media_stream_request.h",
] ]
traits_headers = [ "//content/common/media/media_stream_typemap_traits.h" ] traits_headers = [
"//content/common/media/media_stream_messages.h",
"//content/common/media/media_stream_typemap_traits.h",
]
sources = [ sources = [
"//content/common/media/media_stream_typemap_traits.cc", "//content/common/media/media_stream_typemap_traits.cc",
...@@ -23,5 +26,6 @@ type_mappings = [ ...@@ -23,5 +26,6 @@ type_mappings = [
"content.mojom.MediaStreamRequestResult=content::MediaStreamRequestResult", "content.mojom.MediaStreamRequestResult=content::MediaStreamRequestResult",
"content.mojom.MediaStreamType=content::MediaStreamType", "content.mojom.MediaStreamType=content::MediaStreamType",
"content.mojom.StreamControls=content::StreamControls", "content.mojom.StreamControls=content::StreamControls",
"content.mojom.StreamDeviceInfo=content::StreamDeviceInfo",
"content.mojom.TrackControls=content::TrackControls", "content.mojom.TrackControls=content::TrackControls",
] ]
...@@ -40,26 +40,3 @@ IPC_STRUCT_TRAITS_BEGIN(content::StreamDeviceInfo) ...@@ -40,26 +40,3 @@ IPC_STRUCT_TRAITS_BEGIN(content::StreamDeviceInfo)
IPC_STRUCT_TRAITS_MEMBER(device.camera_calibration) IPC_STRUCT_TRAITS_MEMBER(device.camera_calibration)
IPC_STRUCT_TRAITS_MEMBER(session_id) IPC_STRUCT_TRAITS_MEMBER(session_id)
IPC_STRUCT_TRAITS_END() 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 */,
content::StreamDeviceInfoArray /* audio_device_list */,
content::StreamDeviceInfoArray /* video_device_list */)
// The browser reports that a media device has been stopped. Stopping was
// triggered from the browser process.
IPC_MESSAGE_ROUTED2(MediaStreamMsg_DeviceStopped,
std::string /* label */,
content::StreamDeviceInfo /* the device */)
// TODO(wjia): should DeviceOpen* messages be merged with
// StreamGenerat* ones?
// The browser has opened a device successfully.
IPC_MESSAGE_ROUTED3(MediaStreamMsg_DeviceOpened,
int /* request id */,
std::string /* label */,
content::StreamDeviceInfo /* the device */)
...@@ -201,22 +201,8 @@ void MediaStreamDispatcher::OnDestruct() { ...@@ -201,22 +201,8 @@ void MediaStreamDispatcher::OnDestruct() {
// Do not self-destruct. UserMediaClientImpl owns |this|. // Do not self-destruct. UserMediaClientImpl owns |this|.
} }
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_DeviceStopped,
OnDeviceStopped)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened,
OnDeviceOpened)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void MediaStreamDispatcher::OnStreamGenerated( void MediaStreamDispatcher::OnStreamGenerated(
int request_id, int32_t request_id,
const std::string& label, const std::string& label,
const StreamDeviceInfoArray& audio_array, const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) { const StreamDeviceInfoArray& video_array) {
...@@ -242,43 +228,26 @@ void MediaStreamDispatcher::OnStreamGenerated( ...@@ -242,43 +228,26 @@ void MediaStreamDispatcher::OnStreamGenerated(
} }
} }
void MediaStreamDispatcher::OnDeviceStopped( void MediaStreamDispatcher::OnStreamGenerationFailed(
const std::string& label, int32_t request_id,
const StreamDeviceInfo& device_info) { MediaStreamRequestResult result) {
DVLOG(1) << __func__ << " label=" << label
<< " device_id=" << device_info.device.id;
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
LabelStreamMap::iterator it = label_stream_map_.find(label); for (auto it = requests_.begin(); it != requests_.end(); ++it) {
if (it == label_stream_map_.end()) { Request& request = *it;
// This can happen if a user happen stop a the device from JS at the same if (request.ipc_request != request_id)
// time as the underlying media device is unplugged from the system. continue;
return; if (request.handler.get()) {
request.handler->OnStreamGenerationFailed(request.request_id, result);
DVLOG(1) << __func__ << " request_id=" << request.request_id;
}
requests_.erase(it);
break;
} }
Stream* stream = &it->second;
if (IsAudioInputMediaType(device_info.device.type))
RemoveStreamDeviceFromArray(device_info, &stream->audio_array);
else
RemoveStreamDeviceFromArray(device_info, &stream->video_array);
if (stream->handler.get())
stream->handler->OnDeviceStopped(label, device_info);
// |it| could have already been invalidated in the function call above. So we
// need to check if |label| is still in |label_stream_map_| again.
// Note: this is a quick fix to the crash caused by erasing the invalidated
// iterator from |label_stream_map_| (crbug.com/616884). Future work needs to
// be done to resolve this re-entrancy issue.
it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return;
stream = &it->second;
if (stream->audio_array.empty() && stream->video_array.empty())
label_stream_map_.erase(it);
} }
void MediaStreamDispatcher::OnDeviceOpened( void MediaStreamDispatcher::OnDeviceOpened(
int request_id, int32_t request_id,
const std::string& label, const std::string& label,
const StreamDeviceInfo& device_info) { const StreamDeviceInfo& device_info) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
...@@ -307,9 +276,7 @@ void MediaStreamDispatcher::OnDeviceOpened( ...@@ -307,9 +276,7 @@ void MediaStreamDispatcher::OnDeviceOpened(
} }
} }
void MediaStreamDispatcher::OnStreamGenerationFailed( void MediaStreamDispatcher::OnDeviceOpenFailed(int32_t request_id) {
int32_t request_id,
MediaStreamRequestResult result) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
for (auto it = requests_.begin(); it != requests_.end(); ++it) { for (auto it = requests_.begin(); it != requests_.end(); ++it) {
...@@ -317,7 +284,7 @@ void MediaStreamDispatcher::OnStreamGenerationFailed( ...@@ -317,7 +284,7 @@ void MediaStreamDispatcher::OnStreamGenerationFailed(
if (request.ipc_request != request_id) if (request.ipc_request != request_id)
continue; continue;
if (request.handler.get()) { if (request.handler.get()) {
request.handler->OnStreamGenerationFailed(request.request_id, result); request.handler->OnDeviceOpenFailed(request.request_id);
DVLOG(1) << __func__ << " request_id=" << request.request_id; DVLOG(1) << __func__ << " request_id=" << request.request_id;
} }
requests_.erase(it); requests_.erase(it);
...@@ -325,20 +292,39 @@ void MediaStreamDispatcher::OnStreamGenerationFailed( ...@@ -325,20 +292,39 @@ void MediaStreamDispatcher::OnStreamGenerationFailed(
} }
} }
void MediaStreamDispatcher::OnDeviceOpenFailed(int32_t request_id) { void MediaStreamDispatcher::OnDeviceStopped(
const std::string& label,
const StreamDeviceInfo& device_info) {
DVLOG(1) << __func__ << " label=" << label
<< " device_id=" << device_info.device.id;
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
for (auto it = requests_.begin(); it != requests_.end(); ++it) { LabelStreamMap::iterator it = label_stream_map_.find(label);
Request& request = *it; if (it == label_stream_map_.end()) {
if (request.ipc_request != request_id) // This can happen if a user happen stop a the device from JS at the same
continue; // time as the underlying media device is unplugged from the system.
if (request.handler.get()) { return;
request.handler->OnDeviceOpenFailed(request.request_id);
DVLOG(1) << __func__ << " request_id=" << request.request_id;
}
requests_.erase(it);
break;
} }
Stream* stream = &it->second;
if (IsAudioInputMediaType(device_info.device.type))
RemoveStreamDeviceFromArray(device_info, &stream->audio_array);
else
RemoveStreamDeviceFromArray(device_info, &stream->video_array);
if (stream->handler.get())
stream->handler->OnDeviceStopped(label, device_info);
// |it| could have already been invalidated in the function call above. So we
// need to check if |label| is still in |label_stream_map_| again.
// Note: this is a quick fix to the crash caused by erasing the invalidated
// iterator from |label_stream_map_| (crbug.com/616884). Future work needs to
// be done to resolve this re-entrancy issue.
it = label_stream_map_.find(label);
if (it == label_stream_map_.end())
return;
stream = &it->second;
if (stream->audio_array.empty() && stream->video_array.empty())
label_stream_map_.erase(it);
} }
void MediaStreamDispatcher::BindMediaStreamDispatcherRequest( void MediaStreamDispatcher::BindMediaStreamDispatcherRequest(
......
...@@ -103,6 +103,7 @@ class CONTENT_EXPORT MediaStreamDispatcher ...@@ -103,6 +103,7 @@ class CONTENT_EXPORT MediaStreamDispatcher
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, CancelGenerateStream); FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, CancelGenerateStream);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest,
GetNonScreenCaptureDevices); GetNonScreenCaptureDevices);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, DeviceClosed);
struct Request; struct Request;
...@@ -115,25 +116,20 @@ class CONTENT_EXPORT MediaStreamDispatcher ...@@ -115,25 +116,20 @@ class CONTENT_EXPORT MediaStreamDispatcher
const std::string& interface_name, const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe) override; mojo::ScopedMessagePipeHandle* interface_pipe) override;
void OnDestruct() override; void OnDestruct() override;
bool OnMessageReceived(const IPC::Message& message) override;
// Messages from the browser.
void OnStreamGenerated(
int request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array);
void OnDeviceStopped(const std::string& label,
const StreamDeviceInfo& device_info);
void OnDeviceOpened(
int request_id,
const std::string& label,
const StreamDeviceInfo& device_info);
// mojom::MediaStreamDispatcher implementation. // mojom::MediaStreamDispatcher implementation.
void OnStreamGenerated(int32_t request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) override;
void OnStreamGenerationFailed(int32_t request_id, void OnStreamGenerationFailed(int32_t request_id,
MediaStreamRequestResult result) override; MediaStreamRequestResult result) override;
void OnDeviceOpened(int32_t request_id,
const std::string& label,
const StreamDeviceInfo& device_info) override;
void OnDeviceOpenFailed(int32_t request_id) override; void OnDeviceOpenFailed(int32_t request_id) override;
void OnDeviceStopped(const std::string& label,
const StreamDeviceInfo& device_info) override;
void BindMediaStreamDispatcherRequest( void BindMediaStreamDispatcherRequest(
mojom::MediaStreamDispatcherRequest request); mojom::MediaStreamDispatcherRequest request);
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
namespace content { namespace content {
const int kRouteId = 0;
const int kAudioSessionId = 3; const int kAudioSessionId = 3;
const int kVideoSessionId = 5; const int kVideoSessionId = 5;
const int kScreenSessionId = 7; const int kScreenSessionId = 7;
...@@ -169,9 +168,8 @@ class MediaStreamDispatcherTest : public ::testing::Test { ...@@ -169,9 +168,8 @@ class MediaStreamDispatcherTest : public ::testing::Test {
std::string label = "stream" + base::IntToString(ipc_id); std::string label = "stream" + base::IntToString(ipc_id);
handler_->ResetStoredParameters(); handler_->ResetStoredParameters();
dispatcher_->OnMessageReceived(MediaStreamMsg_StreamGenerated( dispatcher_->OnStreamGenerated(ipc_id, label, audio_device_array,
kRouteId, ipc_id, label, video_device_array);
audio_device_array, video_device_array));
EXPECT_EQ(handler_->request_id_, request_id); EXPECT_EQ(handler_->request_id_, request_id);
EXPECT_EQ(handler_->label_, label); EXPECT_EQ(handler_->label_, label);
...@@ -257,14 +255,12 @@ TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) { ...@@ -257,14 +255,12 @@ TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
// Complete the OpenDevice of request 1. // Complete the OpenDevice of request 1.
std::string stream_label1 = std::string("stream1"); std::string stream_label1 = std::string("stream1");
dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened( dispatcher->OnDeviceOpened(ipc_request_id1, stream_label1, video_device_info);
kRouteId, ipc_request_id1, stream_label1, video_device_info));
EXPECT_EQ(handler1->request_id_, kRequestId1); EXPECT_EQ(handler1->request_id_, kRequestId1);
// Complete the OpenDevice of request 2. // Complete the OpenDevice of request 2.
std::string stream_label2 = std::string("stream2"); std::string stream_label2 = std::string("stream2");
dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened( dispatcher->OnDeviceOpened(ipc_request_id2, stream_label2, video_device_info);
kRouteId, ipc_request_id2, stream_label2, video_device_info));
EXPECT_EQ(handler1->request_id_, kRequestId2); EXPECT_EQ(handler1->request_id_, kRequestId2);
EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
...@@ -330,9 +326,8 @@ TEST_F(MediaStreamDispatcherTest, TestFailure) { ...@@ -330,9 +326,8 @@ TEST_F(MediaStreamDispatcherTest, TestFailure) {
// Complete the creation of stream1. // Complete the creation of stream1.
std::string stream_label1 = std::string("stream1"); std::string stream_label1 = std::string("stream1");
dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( dispatcher->OnStreamGenerated(ipc_request_id1, stream_label1,
kRouteId, ipc_request_id1, stream_label1, audio_device_array, video_device_array);
audio_device_array, video_device_array));
EXPECT_EQ(handler->request_id_, kRequestId1); EXPECT_EQ(handler->request_id_, kRequestId1);
EXPECT_EQ(handler->label_, stream_label1); EXPECT_EQ(handler->label_, stream_label1);
EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId); EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
...@@ -371,16 +366,15 @@ TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) { ...@@ -371,16 +366,15 @@ TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) {
video_device_array[0] = video_device_info; video_device_array[0] = video_device_info;
std::string stream_label1 = "stream1"; std::string stream_label1 = "stream1";
dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( dispatcher->OnStreamGenerated(ipc_request_id1, stream_label1,
kRouteId, ipc_request_id1, stream_label1, audio_device_array, video_device_array);
audio_device_array, video_device_array));
EXPECT_EQ(handler->request_id_, kRequestId1); EXPECT_EQ(handler->request_id_, kRequestId1);
EXPECT_EQ(handler->label_, stream_label1); EXPECT_EQ(handler->label_, stream_label1);
EXPECT_EQ(0u, dispatcher->requests_.size()); EXPECT_EQ(0u, dispatcher->requests_.size());
} }
// Test that the MediaStreamDispatcherEventHandler is notified when the message // Test that the MediaStreamDispatcherEventHandler is notified when the message
// MediaStreamMsg_DeviceStopped is received. // OnDeviceStopped is received.
TEST_F(MediaStreamDispatcherTest, DeviceClosed) { TEST_F(MediaStreamDispatcherTest, DeviceClosed) {
StreamControls controls(true, true); StreamControls controls(true, true);
...@@ -388,8 +382,7 @@ TEST_F(MediaStreamDispatcherTest, DeviceClosed) { ...@@ -388,8 +382,7 @@ TEST_F(MediaStreamDispatcherTest, DeviceClosed) {
const std::string& label = const std::string& label =
CompleteGenerateStream(ipc_request_id, controls, kRequestId1); CompleteGenerateStream(ipc_request_id, controls, kRequestId1);
dispatcher_->OnMessageReceived( dispatcher_->OnDeviceStopped(label, handler_->video_device_);
MediaStreamMsg_DeviceStopped(kRouteId, label, handler_->video_device_));
// Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been
// called. // called.
EXPECT_EQ(label, handler_->device_stopped_label_); EXPECT_EQ(label, handler_->device_stopped_label_);
...@@ -432,14 +425,13 @@ TEST_F(MediaStreamDispatcherTest, GetNonScreenCaptureDevices) { ...@@ -432,14 +425,13 @@ TEST_F(MediaStreamDispatcherTest, GetNonScreenCaptureDevices) {
// Complete the OpenDevice of request 1. // Complete the OpenDevice of request 1.
std::string stream_label1 = std::string("stream1"); std::string stream_label1 = std::string("stream1");
dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened( dispatcher->OnDeviceOpened(ipc_request_id1, stream_label1, video_device_info);
kRouteId, ipc_request_id1, stream_label1, video_device_info));
EXPECT_EQ(handler->request_id_, kRequestId1); EXPECT_EQ(handler->request_id_, kRequestId1);
// Complete the OpenDevice of request 2. // Complete the OpenDevice of request 2.
std::string stream_label2 = std::string("stream2"); std::string stream_label2 = std::string("stream2");
dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened( dispatcher->OnDeviceOpened(ipc_request_id2, stream_label2,
kRouteId, ipc_request_id2, stream_label2, screen_device_info)); screen_device_info);
EXPECT_EQ(handler->request_id_, kRequestId2); EXPECT_EQ(handler->request_id_, kRequestId2);
EXPECT_EQ(dispatcher->requests_.size(), 0u); EXPECT_EQ(dispatcher->requests_.size(), 0u);
......
...@@ -393,7 +393,7 @@ class UserMediaClientImplUnderTest : public UserMediaClientImpl { ...@@ -393,7 +393,7 @@ class UserMediaClientImplUnderTest : public UserMediaClientImpl {
class UserMediaClientImplTest : public ::testing::TestWithParam<bool> { class UserMediaClientImplTest : public ::testing::TestWithParam<bool> {
public: public:
UserMediaClientImplTest() UserMediaClientImplTest()
: binding_user_media(&media_devices_dispatcher_), : binding_user_media_(&media_devices_dispatcher_),
binding_event_dispatcher_(&media_devices_dispatcher_) { binding_event_dispatcher_(&media_devices_dispatcher_) {
if (GetParam()) { if (GetParam()) {
scoped_feature_list_.InitAndEnableFeature( scoped_feature_list_.InitAndEnableFeature(
...@@ -414,7 +414,7 @@ class UserMediaClientImplTest : public ::testing::TestWithParam<bool> { ...@@ -414,7 +414,7 @@ class UserMediaClientImplTest : public ::testing::TestWithParam<bool> {
dependency_factory_.get(), dependency_factory_.get(),
std::unique_ptr<MediaStreamDispatcher>(ms_dispatcher_))); std::unique_ptr<MediaStreamDispatcher>(ms_dispatcher_)));
::mojom::MediaDevicesDispatcherHostPtr user_media_host_proxy; ::mojom::MediaDevicesDispatcherHostPtr user_media_host_proxy;
binding_user_media.Bind(mojo::MakeRequest(&user_media_host_proxy)); binding_user_media_.Bind(mojo::MakeRequest(&user_media_host_proxy));
user_media_client_impl_->SetMediaDevicesDispatcherForTesting( user_media_client_impl_->SetMediaDevicesDispatcherForTesting(
std::move(user_media_host_proxy)); std::move(user_media_host_proxy));
base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher = base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher =
...@@ -533,7 +533,7 @@ class UserMediaClientImplTest : public ::testing::TestWithParam<bool> { ...@@ -533,7 +533,7 @@ class UserMediaClientImplTest : public ::testing::TestWithParam<bool> {
MockMediaStreamDispatcher* ms_dispatcher_; // Owned by |used_media_impl_|. MockMediaStreamDispatcher* ms_dispatcher_; // Owned by |used_media_impl_|.
MockMojoMediaStreamDispatcherHost mock_dispatcher_host_; MockMojoMediaStreamDispatcherHost mock_dispatcher_host_;
MockMediaDevicesDispatcherHost media_devices_dispatcher_; MockMediaDevicesDispatcherHost media_devices_dispatcher_;
mojo::Binding<::mojom::MediaDevicesDispatcherHost> binding_user_media; mojo::Binding<::mojom::MediaDevicesDispatcherHost> binding_user_media_;
mojo::Binding<::mojom::MediaDevicesDispatcherHost> binding_event_dispatcher_; mojo::Binding<::mojom::MediaDevicesDispatcherHost> binding_event_dispatcher_;
std::unique_ptr<UserMediaClientImplUnderTest> user_media_client_impl_; std::unique_ptr<UserMediaClientImplUnderTest> user_media_client_impl_;
......
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