Commit 049d6417 authored by mcasas's avatar mcasas Committed by Commit bot

VideoCapture: remove last remnants of IPC

In this CL:
- On Browser: VCHost is not a BrowserMessageFilter nor
a  BrowserAssociatedInterface, and instead works like a
normal service implementation, Create()d on request and
hanging from the render process host.

-On renderer:
 - VideoCaptureMessageFilter, which was specific for
IPC, is removed altogether.
 - VCImpl (the "client"), does not need the IPC, and
instead gets an InterfacePtr to the remote VideoCaptureHost,
and uses it.

All that allows for a few simplifications around like, e.g.
VCImpl doesn't need to keep track of  |clients_pending_on_filter_|
nor of IO thread explicitly (using a ThreadChecker instead),
and also I cleaned up a bit more the unittests.

BUG=651897

Review-Url: https://chromiumcodereview.appspot.com/2430313007
Cr-Commit-Position: refs/heads/master@{#426903}
parent c04d1756
......@@ -11,22 +11,28 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/video_capture_messages.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
: BrowserMessageFilter(VideoCaptureMsgStart),
BrowserAssociatedInterface(this, this),
media_stream_manager_(media_stream_manager) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
: media_stream_manager_(media_stream_manager),
weak_factory_(this) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
VideoCaptureHost::~VideoCaptureHost() {}
// static
void VideoCaptureHost::Create(MediaStreamManager* media_stream_manager,
mojom::VideoCaptureHostRequest request) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
mojo::MakeStrongBinding(
base::MakeUnique<VideoCaptureHost>(media_stream_manager),
std::move(request));
}
void VideoCaptureHost::OnChannelClosing() {
// Since the IPC sender is gone, close all requested VideoCaptureDevices.
VideoCaptureHost::~VideoCaptureHost() {
for (auto it = controllers_.begin(); it != controllers_.end(); ) {
const base::WeakPtr<VideoCaptureController>& controller = it->second;
if (controller) {
......@@ -43,21 +49,13 @@ void VideoCaptureHost::OnChannelClosing() {
}
}
void VideoCaptureHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message) {
NOTREACHED() << __func__ << " should not be receiving messages";
return true;
}
void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoCaptureHost::DoError, this, controller_id));
base::Bind(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(),
controller_id));
}
void VideoCaptureHost::OnBufferCreated(VideoCaptureControllerID controller_id,
......@@ -114,7 +112,8 @@ void VideoCaptureHost::OnEnded(VideoCaptureControllerID controller_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VideoCaptureHost::DoEnded, this, controller_id));
base::Bind(&VideoCaptureHost::DoEnded, weak_factory_.GetWeakPtr(),
controller_id));
}
void VideoCaptureHost::Start(int32_t device_id,
......@@ -138,11 +137,9 @@ void VideoCaptureHost::Start(int32_t device_id,
controllers_[controller_id] = base::WeakPtr<VideoCaptureController>();
media_stream_manager_->video_capture_manager()->StartCaptureForClient(
session_id,
params,
controller_id,
this,
base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id));
session_id, params, controller_id, this,
base::Bind(&VideoCaptureHost::OnControllerAdded,
weak_factory_.GetWeakPtr(), device_id));
}
void VideoCaptureHost::Stop(int32_t device_id) {
......
......@@ -15,9 +15,6 @@
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
#include "content/common/video_capture.mojom.h"
#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
#include "ipc/ipc_message.h"
namespace content {
class MediaStreamManager;
......@@ -27,28 +24,19 @@ class MediaStreamManager;
// stream) and a VideoCaptureController in the browser process (which provides
// the stream from a video device). Every remote client is identified via a
// unique |device_id|, and is paired with a single VideoCaptureController.
//
// This class is owned by RenderProcessHostImpl, and instantiated on UI thread,
// but all other operations and method calls happen on IO thread.
class CONTENT_EXPORT VideoCaptureHost
: public BrowserMessageFilter,
public VideoCaptureControllerEventHandler,
public BrowserAssociatedInterface<mojom::VideoCaptureHost>,
: public VideoCaptureControllerEventHandler,
public mojom::VideoCaptureHost {
public:
explicit VideoCaptureHost(MediaStreamManager* media_stream_manager);
private:
friend class BrowserThread;
friend class base::DeleteHelper<VideoCaptureHost>;
friend class VideoCaptureHostTest;
static void Create(MediaStreamManager* media_stream_manager,
mojom::VideoCaptureHostRequest request);
~VideoCaptureHost() override;
// BrowserMessageFilter implementation.
void OnChannelClosing() override;
void OnDestruct() const override;
bool OnMessageReceived(const IPC::Message& message) override;
private:
friend class VideoCaptureHostTest;
// VideoCaptureControllerEventHandler implementation.
void OnError(VideoCaptureControllerID id) override;
......@@ -113,6 +101,8 @@ class CONTENT_EXPORT VideoCaptureHost
// Start() and the corresponding Stop().
std::map<int32_t, mojom::VideoCaptureObserverPtr> device_id_to_observer_map_;
base::WeakPtrFactory<VideoCaptureHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHost);
};
......
......@@ -23,7 +23,6 @@
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_requester.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/video_capture_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_context.h"
......@@ -32,6 +31,7 @@
#include "media/audio/mock_audio_manager.h"
#include "media/base/media_switches.h"
#include "media/base/video_capture_types.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -112,8 +112,7 @@ class VideoCaptureHostTest : public testing::Test,
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
// Create a Host and connect it to a simulated IPC channel.
host_ = new VideoCaptureHost(media_stream_manager_.get());
host_->OnChannelConnected(base::GetCurrentProcId());
host_.reset(new VideoCaptureHost(media_stream_manager_.get()));
OpenSession();
}
......@@ -124,9 +123,6 @@ class VideoCaptureHostTest : public testing::Test,
CloseSession();
// Simulate closing the IPC sender.
host_->OnChannelClosing();
// Release the reference to the mock object. The object will be destructed
// on the current message loop.
host_ = nullptr;
......@@ -312,7 +308,7 @@ class VideoCaptureHostTest : public testing::Test,
int opened_session_id_;
std::string opened_device_label_;
scoped_refptr<VideoCaptureHost> host_;
std::unique_ptr<VideoCaptureHost> host_;
mojo::Binding<mojom::VideoCaptureObserver> observer_binding_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
......
......@@ -1097,7 +1097,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(audio_renderer_host_.get());
AddFilter(
new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager()));
AddFilter(new VideoCaptureHost(media_stream_manager));
AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(), GetID()));
AddFilter(new ClipboardMessageFilter(blob_storage_context));
......@@ -1286,6 +1285,10 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(
base::Bind(&URLLoaderFactoryImpl::Create, resource_message_filter_));
registry->AddInterface(
base::Bind(&VideoCaptureHost::Create,
BrowserMainLoop::GetInstance()->media_stream_manager()));
// This is to support usage of WebSockets in cases in which there is no
// associated RenderFrame (e.g., Shared Workers).
AddUIThreadInterface(
......
......@@ -217,7 +217,6 @@ source_set("common") {
"media/midi_messages.h",
"media/surface_view_manager_messages_android.h",
"media/video_capture.h",
"media/video_capture_messages.h",
"memory_messages.h",
"message_port_messages.h",
"navigation_gesture.h",
......
......@@ -33,7 +33,6 @@
#include "content/common/media/media_stream_track_metrics_host_messages.h"
#include "content/common/media/midi_messages.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/memory_messages.h"
#include "content/common/message_port_messages.h"
#include "content/common/page_messages.h"
......
// Copyright (c) 2012 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/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START VideoCaptureMsgStart
// TODO(mcasas): Remove this message when the Video Capture IPC communication is
// completely migrated to Mojo, https://crbug.com/651897.
IPC_MESSAGE_CONTROL0(VideoCaptureMsg_Noop)
......@@ -249,8 +249,6 @@ target(link_target_type, "renderer") {
"media/video_capture_impl.h",
"media/video_capture_impl_manager.cc",
"media/video_capture_impl_manager.h",
"media/video_capture_message_filter.cc",
"media/video_capture_message_filter.h",
"media/web_media_element_source_utils.cc",
"media/web_media_element_source_utils.h",
"media/webmediaplayer_ms.cc",
......
......@@ -16,39 +16,20 @@
#include "content/common/content_export.h"
#include "content/common/media/video_capture.h"
#include "content/common/video_capture.mojom.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/video_capture_message_filter.h"
#include "media/base/video_capture_types.h"
#include "media/base/video_frame.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace content {
// VideoCaptureImpl represents a capture device in renderer process. It provides
// interfaces for clients to Start/Stop capture. It also communicates to clients
// when buffer is ready, state of capture device is changed.
//
// VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter to receive
// notification of the browser process being ready to communicate.
//
// VideoCaptureImpl is an IO thread only object. See the comments in
// video_capture_impl_manager.cc for the lifetime of this object.
// All methods must be called on the IO thread.
//
// This is an internal class used by VideoCaptureImplManager only. Do not access
// this directly.
class CONTENT_EXPORT VideoCaptureImpl
: public VideoCaptureMessageFilter::Delegate,
public mojom::VideoCaptureObserver {
// an interface for clients to command the capture (Start, Stop, etc), and
// communicates back to these clients e.g. the capture state or incoming
// captured VideoFrames. VideoCaptureImpl is created in the main Renderer thread
// but otherwise operates on |io_task_runner_|, which is usually the IO thread.
class CONTENT_EXPORT VideoCaptureImpl : public mojom::VideoCaptureObserver {
public:
VideoCaptureImpl(
media::VideoCaptureSessionId session_id,
VideoCaptureMessageFilter* filter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
explicit VideoCaptureImpl(media::VideoCaptureSessionId session_id);
~VideoCaptureImpl() override;
// Stop/resume delivering video frames to clients, based on flag |suspend|.
......@@ -93,25 +74,15 @@ class CONTENT_EXPORT VideoCaptureImpl
// renderer.
class ClientBuffer;
// Contains information for a video capture client. Including parameters
// for capturing and callbacks to the client.
struct ClientInfo {
ClientInfo();
ClientInfo(const ClientInfo& other);
~ClientInfo();
media::VideoCaptureParams params;
VideoCaptureStateUpdateCB state_update_cb;
VideoCaptureDeliverFrameCB deliver_frame_cb;
};
// Contains information about a video capture client, including capture
// parameters callbacks to the client.
struct ClientInfo;
using ClientInfoMap = std::map<int, ClientInfo>;
using BufferFinishedCallback =
base::Callback<void(const gpu::SyncToken& sync_token,
double consumer_resource_utilization)>;
// VideoCaptureMessageFilter::Delegate interface implementation.
void OnDelegateAdded(int32_t device_id) override;
// mojom::VideoCaptureObserver implementation.
void OnStateChanged(mojom::VideoCaptureState state) override;
void OnBufferCreated(int32_t buffer_id,
......@@ -151,40 +122,40 @@ class CONTENT_EXPORT VideoCaptureImpl
std::unique_ptr<gpu::SyncToken> release_sync_token,
const BufferFinishedCallback& callback_to_io_thread);
const scoped_refptr<VideoCaptureMessageFilter> message_filter_;
int device_id_;
// |device_id_| and |session_id_| are different concepts, but we reuse the
// same numerical value, passed on construction.
const int device_id_;
const int session_id_;
mojom::VideoCaptureHostAssociatedPtr video_capture_host_;
// |video_capture_host_| is an IO-thread InterfacePtr to a remote service
// implementation and is created by binding |video_capture_host_info_|,
// unless a |video_capture_host_for_testing_| has been injected.
mojom::VideoCaptureHostPtrInfo video_capture_host_info_;
mojom::VideoCaptureHostPtr video_capture_host_;
mojom::VideoCaptureHost* video_capture_host_for_testing_;
mojo::Binding<mojom::VideoCaptureObserver> observer_binding_;
// Buffers available for sending to the client.
typedef std::map<int32_t, scoped_refptr<ClientBuffer>> ClientBufferMap;
using ClientBufferMap = std::map<int32_t, scoped_refptr<ClientBuffer>>;
ClientBufferMap client_buffers_;
ClientInfoMap clients_;
ClientInfoMap clients_pending_on_filter_;
ClientInfoMap clients_pending_on_restart_;
// Member params_ represents the video format requested by the
// client to this class via StartCapture().
// Video format requested by the client to this class via StartCapture().
media::VideoCaptureParams params_;
// The device's first captured frame reference time sent from browser process
// side.
// First captured frame reference time sent from browser process side.
base::TimeTicks first_frame_ref_time_;
VideoCaptureState state_;
// IO message loop reference for checking correct class operation.
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
base::ThreadChecker io_thread_checker_;
// WeakPtrFactory pointing back to |this| object, for use with
// media::VideoFrames constructed in OnBufferReceived() from buffers cached
// in |client_buffers_|.
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<VideoCaptureImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureImpl);
......
......@@ -32,7 +32,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/child_process.h"
#include "content/renderer/media/video_capture_impl.h"
#include "content/renderer/media/video_capture_message_filter.h"
namespace content {
......@@ -59,7 +58,6 @@ struct VideoCaptureImplManager::DeviceEntry {
VideoCaptureImplManager::VideoCaptureImplManager()
: next_client_id_(0),
filter_(new VideoCaptureMessageFilter()),
render_main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
is_suspending_all_(false),
weak_factory_(this) {}
......@@ -78,6 +76,7 @@ VideoCaptureImplManager::~VideoCaptureImplManager() {
base::Closure VideoCaptureImplManager::UseDevice(
media::VideoCaptureSessionId id) {
DVLOG(1) << __func__ << " session id: " << id;
DCHECK(render_main_task_runner_->BelongsToCurrentThread());
auto it = std::find_if(
devices_.begin(), devices_.end(),
......@@ -86,11 +85,9 @@ base::Closure VideoCaptureImplManager::UseDevice(
devices_.push_back(DeviceEntry());
it = devices_.end() - 1;
it->session_id = id;
it->impl = CreateVideoCaptureImplForTesting(id, filter_.get());
if (!it->impl) {
it->impl.reset(new VideoCaptureImpl(
id, filter_.get(), ChildProcess::current()->io_task_runner()));
}
it->impl = CreateVideoCaptureImplForTesting(id);
if (!it->impl)
it->impl.reset(new VideoCaptureImpl(id));
}
++it->client_count;
......@@ -205,8 +202,7 @@ void VideoCaptureImplManager::GetDeviceFormatsInUse(
std::unique_ptr<VideoCaptureImpl>
VideoCaptureImplManager::CreateVideoCaptureImplForTesting(
media::VideoCaptureSessionId id,
VideoCaptureMessageFilter* filter) const {
media::VideoCaptureSessionId session_id) const {
return std::unique_ptr<VideoCaptureImpl>();
}
......
......@@ -23,7 +23,6 @@
namespace content {
class VideoCaptureImpl;
class VideoCaptureMessageFilter;
// TODO(hclam): This class should be renamed to VideoCaptureService.
......@@ -97,14 +96,8 @@ class CONTENT_EXPORT VideoCaptureImplManager {
// an individual session, please call Suspend(id) or Resume(id).
void SuspendDevices(bool suspend);
VideoCaptureMessageFilter* video_capture_message_filter() const {
return filter_.get();
}
protected:
virtual std::unique_ptr<VideoCaptureImpl> CreateVideoCaptureImplForTesting(
media::VideoCaptureSessionId id,
VideoCaptureMessageFilter* filter) const;
media::VideoCaptureSessionId session_id) const;
private:
// Holds bookkeeping info for each VideoCaptureImpl shared by clients.
......@@ -120,8 +113,6 @@ class CONTENT_EXPORT VideoCaptureImplManager {
// The ID is global for the render process.
int next_client_id_;
const scoped_refptr<VideoCaptureMessageFilter> filter_;
// Hold a pointer to the Render Main message loop to check we operate on the
// right thread.
const scoped_refptr<base::SingleThreadTaskRunner> render_main_task_runner_;
......
......@@ -12,11 +12,9 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "content/child/child_process.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/video_capture.mojom.h"
#include "content/renderer/media/video_capture_impl.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_message_filter.h"
#include "media/base/bind_to_current_loop.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -50,12 +48,9 @@ class MockVideoCaptureImpl : public VideoCaptureImpl,
public mojom::VideoCaptureHost {
public:
MockVideoCaptureImpl(media::VideoCaptureSessionId session_id,
VideoCaptureMessageFilter* filter,
PauseResumeCallback* pause_callback,
base::Closure destruct_callback)
: VideoCaptureImpl(session_id,
filter,
ChildProcess::current()->io_task_runner()),
: VideoCaptureImpl(session_id),
pause_callback_(pause_callback),
destruct_callback_(destruct_callback) {}
......@@ -99,24 +94,22 @@ class MockVideoCaptureImpl : public VideoCaptureImpl,
class MockVideoCaptureImplManager : public VideoCaptureImplManager {
public:
MockVideoCaptureImplManager(PauseResumeCallback* pause_callback,
base::Closure destruct_video_capture_callback)
base::Closure stop_capture_callback)
: pause_callback_(pause_callback),
destruct_video_capture_callback_(destruct_video_capture_callback) {}
stop_capture_callback_(stop_capture_callback) {}
~MockVideoCaptureImplManager() override {}
private:
std::unique_ptr<VideoCaptureImpl> CreateVideoCaptureImplForTesting(
media::VideoCaptureSessionId id,
VideoCaptureMessageFilter* filter) const override {
media::VideoCaptureSessionId session_id) const override {
auto video_capture_impl = base::MakeUnique<MockVideoCaptureImpl>(
id, filter, pause_callback_, destruct_video_capture_callback_);
video_capture_impl->SetVideoCaptureHostForTesting(
video_capture_impl.get());
session_id, pause_callback_, stop_capture_callback_);
video_capture_impl->SetVideoCaptureHostForTesting(video_capture_impl.get());
return std::move(video_capture_impl);
}
PauseResumeCallback* const pause_callback_;
const base::Closure destruct_video_capture_callback_;
const base::Closure stop_capture_callback_;
DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImplManager);
};
......@@ -151,11 +144,6 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
same_session_id ? 0 : static_cast<media::VideoCaptureSessionId>(i),
params);
}
child_process_.io_task_runner()->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureMessageFilter::OnFilterAdded,
base::Unretained(manager_->video_capture_message_filter()),
nullptr));
run_loop.Run();
return stop_callbacks;
}
......
......@@ -22,7 +22,7 @@ using ::testing::WithArgs;
namespace content {
const int kSessionId = 1;
const int kSessionId = 11;
void RunEmptyFormatsCallback(const VideoCaptureDeviceFormatsCB& callback) {
media::VideoCaptureFormats formats;
......@@ -76,18 +76,13 @@ class MockMojoVideoCaptureHost : public mojom::VideoCaptureHost {
// This class encapsulates a VideoCaptureImpl under test and the necessary
// accessory classes, namely:
// - a VideoCaptureMessageFilter;
// - a MockMojoVideoCaptureHost, mimicking the RendererHost;
// - a few callbacks that are bound when calling operations of VideoCaptureImpl
// and on which we set expectations.
class VideoCaptureImplTest : public ::testing::Test {
public:
VideoCaptureImplTest()
: message_filter_(new VideoCaptureMessageFilter),
video_capture_impl_(
new VideoCaptureImpl(kSessionId,
message_filter_.get(),
base::ThreadTaskRunnerHandle::Get())) {
: video_capture_impl_(new VideoCaptureImpl(kSessionId)) {
params_small_.requested_format = media::VideoCaptureFormat(
gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420);
params_large_.requested_format = media::VideoCaptureFormat(
......@@ -95,7 +90,6 @@ class VideoCaptureImplTest : public ::testing::Test {
video_capture_impl_->SetVideoCaptureHostForTesting(
&mock_video_capture_host_);
video_capture_impl_->device_id_ = 2;
}
protected:
......@@ -171,7 +165,6 @@ class VideoCaptureImplTest : public ::testing::Test {
const base::MessageLoop message_loop_;
const ChildProcess child_process_;
const scoped_refptr<VideoCaptureMessageFilter> message_filter_;
const std::unique_ptr<VideoCaptureImpl> video_capture_impl_;
MockMojoVideoCaptureHost mock_video_capture_host_;
media::VideoCaptureParams params_small_;
......
// Copyright (c) 2012 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/video_capture_message_filter.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/view_messages.h"
#include "ipc/ipc_sender.h"
namespace content {
VideoCaptureMessageFilter::VideoCaptureMessageFilter()
: last_device_id_(0), channel_(nullptr) {}
void VideoCaptureMessageFilter::AddDelegate(Delegate* delegate) {
DVLOG(1) << __func__;
last_device_id_++;
DCHECK_GE(last_device_id_, 1);
DCHECK(!base::ContainsKey(delegates_, last_device_id_));
if (channel_) {
delegates_[last_device_id_] = delegate;
delegate->OnDelegateAdded(last_device_id_);
} else {
pending_delegates_[last_device_id_] = delegate;
}
}
void VideoCaptureMessageFilter::RemoveDelegate(Delegate* delegate) {
DVLOG(1) << __func__;
for (Delegates::iterator it = delegates_.begin(); it != delegates_.end();
it++) {
if (it->second == delegate) {
delegates_.erase(it);
break;
}
}
for (Delegates::iterator it = pending_delegates_.begin();
it != pending_delegates_.end(); it++) {
if (it->second == delegate) {
pending_delegates_.erase(it);
break;
}
}
}
bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(VideoCaptureMessageFilter, message)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_Noop, DoNothing)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void VideoCaptureMessageFilter::OnFilterAdded(IPC::Channel* channel) {
DVLOG(1) << __func__;
channel_ = channel;
for (const auto& pending_delegate : pending_delegates_) {
pending_delegate.second->OnDelegateAdded(pending_delegate.first);
delegates_[pending_delegate.first] = pending_delegate.second;
}
pending_delegates_.clear();
}
void VideoCaptureMessageFilter::OnFilterRemoved() {
channel_ = nullptr;
}
void VideoCaptureMessageFilter::OnChannelClosing() {
channel_ = nullptr;
}
VideoCaptureMessageFilter::~VideoCaptureMessageFilter() {}
} // namespace content
// Copyright (c) 2012 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_VIDEO_CAPTURE_MESSAGE_FILTER_H_
#define CONTENT_RENDERER_MEDIA_VIDEO_CAPTURE_MESSAGE_FILTER_H_
#include <stdint.h>
#include <map>
#include "base/macros.h"
#include "content/common/content_export.h"
#include "ipc/message_filter.h"
namespace content {
// MessageFilter that notifies a (series of) Delegates of incoming video capture
// connections. VideoCaptureMessageFilter is operated on IO thread of render
// process.
class CONTENT_EXPORT VideoCaptureMessageFilter : public IPC::MessageFilter {
public:
class CONTENT_EXPORT Delegate {
public:
// Called when a delegate has been added to the filter's delegate list.
// |device_id| is the device id for the delegate.
virtual void OnDelegateAdded(int32_t device_id) = 0;
protected:
virtual ~Delegate() {}
};
VideoCaptureMessageFilter();
// Add a delegate to the map.
void AddDelegate(Delegate* delegate);
// Remove a delegate from the map.
void RemoveDelegate(Delegate* delegate);
IPC::Channel* channel() const { return channel_; }
// IPC::MessageFilter override. Called on IO thread.
bool OnMessageReceived(const IPC::Message& message) override;
void OnFilterAdded(IPC::Channel* channel) override;
void OnFilterRemoved() override;
void OnChannelClosing() override;
void DoNothing() const {}
protected:
~VideoCaptureMessageFilter() override;
private:
// A map of device ids to delegates.
using Delegates = std::map<int32_t, Delegate*>;
Delegates delegates_;
Delegates pending_delegates_;
int32_t last_device_id_;
IPC::Channel* channel_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureMessageFilter);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_VIDEO_CAPTURE_MESSAGE_FILTER_H_
// Copyright (c) 2012 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 <stdint.h>
#include "base/process/process_handle.h"
#include "build/build_config.h"
#include "content/renderer/media/video_capture_message_filter.h"
#include "ipc/ipc_test_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::StrictMock;
using ::testing::WithArgs;
namespace content {
namespace {
class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
public:
MockVideoCaptureDelegate() : device_id_(0) {
ON_CALL(*this, OnDelegateAdded(_))
.WillByDefault(WithArgs<0>(
Invoke(this, &MockVideoCaptureDelegate::DoOnDelegateAdded)));
}
MOCK_METHOD1(OnDelegateAdded, void(int32_t));
void DoOnDelegateAdded(int32_t device_id) {
ASSERT_NE(0, device_id);
ASSERT_EQ(0, device_id_);
device_id_ = device_id;
}
int device_id() { return device_id_; }
private:
int device_id_;
};
} // anonymous namespace
TEST(VideoCaptureMessageFilterTest, Basic) {
scoped_refptr<VideoCaptureMessageFilter> filter(
new VideoCaptureMessageFilter());
IPC::TestSink channel;
filter->OnFilterAdded(&channel);
MockVideoCaptureDelegate delegate;
EXPECT_CALL(delegate, OnDelegateAdded(1));
filter->AddDelegate(&delegate);
ASSERT_EQ(1, delegate.device_id());
Mock::VerifyAndClearExpectations(&delegate);
}
TEST(VideoCaptureMessageFilterTest, Delegates) {
scoped_refptr<VideoCaptureMessageFilter> filter(
new VideoCaptureMessageFilter());
IPC::TestSink channel;
filter->OnFilterAdded(&channel);
MockVideoCaptureDelegate delegate1;
MockVideoCaptureDelegate delegate2;
EXPECT_CALL(delegate1, OnDelegateAdded(1));
EXPECT_CALL(delegate2, OnDelegateAdded(2));
filter->AddDelegate(&delegate1);
filter->AddDelegate(&delegate2);
ASSERT_EQ(1, delegate1.device_id());
ASSERT_EQ(2, delegate2.device_id());
// Remove the delegates. Make sure they won't get called.
filter->RemoveDelegate(&delegate1);
filter->RemoveDelegate(&delegate2);
}
} // namespace content
......@@ -111,7 +111,6 @@
#include "content/renderer/media/render_media_client.h"
#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_message_filter.h"
#include "content/renderer/net_info_helper.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "content/renderer/render_frame_proxy.h"
......@@ -697,7 +696,6 @@ void RenderThreadImpl::Init(
AddFilter(db_message_filter_.get());
vc_manager_.reset(new VideoCaptureImplManager());
AddFilter(vc_manager_->video_capture_message_filter());
browser_plugin_manager_.reset(new BrowserPluginManager());
AddObserver(browser_plugin_manager_.get());
......@@ -949,7 +947,6 @@ void RenderThreadImpl::Shutdown() {
// by the PC factory. Once those tasks have been freed, the factory can be
// deleted.
#endif
RemoveFilter(vc_manager_->video_capture_message_filter());
vc_manager_.reset();
RemoveFilter(db_message_filter_.get());
......
......@@ -1310,7 +1310,6 @@ test("content_unittests") {
"../renderer/media/render_media_log_unittest.cc",
"../renderer/media/video_capture_impl_manager_unittest.cc",
"../renderer/media/video_capture_impl_unittest.cc",
"../renderer/media/video_capture_message_filter_unittest.cc",
"../renderer/media/webmediaplayer_ms_unittest.cc",
"../renderer/peripheral_content_heuristic_unittest.cc",
"../renderer/render_thread_impl_unittest.cc",
......
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