create one video capture message filter per renderer process
BUG=none
TEST=try bots
Review URL: http://codereview.chromium.org/7058055

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88396 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index f98daadf..4bded54c 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -141,6 +141,8 @@
         'renderer/v8_value_converter.h',
         'renderer/video_capture_message_filter.cc',
         'renderer/video_capture_message_filter.h',
+        'renderer/video_capture_message_filter_creator.cc',
+        'renderer/video_capture_message_filter_creator.h',
         'renderer/webplugin_delegate_proxy.cc',
         'renderer/webplugin_delegate_proxy.h',
         'renderer/websharedworker_proxy.cc',
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc
index da02e2f..aed3ef7a 100644
--- a/content/renderer/media/video_capture_impl.cc
+++ b/content/renderer/media/video_capture_impl.cc
@@ -68,7 +68,7 @@
 
 void VideoCaptureImpl::DeInit(Task* task) {
   if (state_ == kStarted)
-    message_filter_->Send(new VideoCaptureHostMsg_Stop(0, device_id_));
+    Send(new VideoCaptureHostMsg_Stop(0, device_id_));
 
   base::MessageLoopProxy* io_message_loop_proxy =
       ChildProcess::current()->io_message_loop_proxy();
@@ -229,8 +229,7 @@
   }
 
   if (state_ != kStarted) {
-    message_filter_->Send(
-        new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
+    Send(new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
     return;
   }
 
@@ -259,8 +258,7 @@
     it->first->OnBufferReady(this, buffer);
   }
 
-  message_filter_->Send(
-      new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
+  Send(new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
 }
 
 void VideoCaptureImpl::OnStateChanged(
@@ -342,7 +340,7 @@
 
   if (state_ == kStarted) {
     state_ = kStopping;
-    message_filter_->Send(new VideoCaptureHostMsg_Stop(0, device_id_));
+    Send(new VideoCaptureHostMsg_Stop(0, device_id_));
     width_ = height_ = 0;
   }
 }
@@ -369,7 +367,7 @@
   params.height = height_;
   params.session_id = session_id_;
 
-  message_filter_->Send(new VideoCaptureHostMsg_Start(0, device_id_, params));
+  Send(new VideoCaptureHostMsg_Start(0, device_id_, params));
   state_ = kStarted;
   for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) {
     it->first->OnStarted(this);
@@ -384,3 +382,12 @@
   base::ScopedTaskRunner task_runner(task);
   message_filter_->RemoveDelegate(this);
 }
+
+void VideoCaptureImpl::Send(IPC::Message* message) {
+  base::MessageLoopProxy* io_message_loop_proxy =
+      ChildProcess::current()->io_message_loop_proxy();
+
+  io_message_loop_proxy->PostTask(FROM_HERE,
+      NewRunnableMethod(message_filter_.get(),
+                        &VideoCaptureMessageFilter::Send, message));
+}
diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h
index 68549ef1..fd4750cf 100644
--- a/content/renderer/media/video_capture_impl.h
+++ b/content/renderer/media/video_capture_impl.h
@@ -76,6 +76,7 @@
   void StartCaptureInternal();
   void AddDelegateOnIOThread();
   void RemoveDelegateOnIOThread(Task* task);
+  virtual void Send(IPC::Message* message);
 
   scoped_refptr<VideoCaptureMessageFilter> message_filter_;
   media::VideoCaptureSessionId session_id_;
diff --git a/content/renderer/media/video_capture_impl_manager.cc b/content/renderer/media/video_capture_impl_manager.cc
index b8611a6..9985d75 100644
--- a/content/renderer/media/video_capture_impl_manager.cc
+++ b/content/renderer/media/video_capture_impl_manager.cc
@@ -5,44 +5,9 @@
 #include "content/renderer/media/video_capture_impl_manager.h"
 
 #include "base/memory/singleton.h"
-#include "content/common/child_process.h"
-#include "content/common/child_thread.h"
-#include "content/common/video_capture_messages.h"
-#include "content/common/view_messages.h"
+#include "content/renderer/video_capture_message_filter_creator.h"
 #include "media/base/message_loop_factory_impl.h"
 
-namespace {
-
-// VideoCaptureMessageFilterCreator is to be used as a singleton so we can get
-// access to a shared VideoCaptureMessageFilter.
-// Example usage:
-//   VideoCaptureMessageFilter* filter =
-//       VideoCaptureMessageFilterCreator::SharedFilter();
-
-class VideoCaptureMessageFilterCreator {
- public:
-  VideoCaptureMessageFilterCreator() {
-    int routing_id;
-    ChildThread::current()->Send(
-        new ViewHostMsg_GenerateRoutingID(&routing_id));
-    filter_ = new VideoCaptureMessageFilter(routing_id);
-    filter_->AddFilter();
-  }
-
-  static VideoCaptureMessageFilter* SharedFilter() {
-    return GetInstance()->filter_.get();
-  }
-
-  static VideoCaptureMessageFilterCreator* GetInstance() {
-    return Singleton<VideoCaptureMessageFilterCreator>::get();
-  }
-
- private:
-  scoped_refptr<VideoCaptureMessageFilter> filter_;
-};
-
-}  // namespace
-
 VideoCaptureImplManager::VideoCaptureImplManager() {
   ml_factory_.reset(new media::MessageLoopFactoryImpl());
   ml_proxy_ = ml_factory_->GetMessageLoopProxy("VC manager");
diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc
index e3db8b6..b5134257 100644
--- a/content/renderer/media/video_capture_impl_unittest.cc
+++ b/content/renderer/media/video_capture_impl_unittest.cc
@@ -13,9 +13,8 @@
 #define DEFAULT_CAPABILITY {176, 144, 30, 0, media::VideoFrame::I420, \
     false, false }
 
-ACTION_P(DeleteMessage, return_value) {
+ACTION(DeleteMessage) {
   delete arg0;
-  return return_value;
 }
 
 class MockVideoCaptureMessageFilter : public VideoCaptureMessageFilter {
@@ -25,7 +24,6 @@
 
   // Filter implementation.
   MOCK_METHOD1(Send, bool(IPC::Message* message));
-  MOCK_METHOD0(ReadyToSend, bool());
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureMessageFilter);
@@ -54,6 +52,18 @@
 
 class VideoCaptureImplTest : public ::testing::Test {
  public:
+  class MockVideoCaptureImpl : public VideoCaptureImpl {
+   public:
+    MockVideoCaptureImpl(const media::VideoCaptureSessionId id,
+                         scoped_refptr<base::MessageLoopProxy> ml_proxy,
+                         VideoCaptureMessageFilter* filter)
+        : VideoCaptureImpl(id, ml_proxy, filter) {
+    }
+    virtual ~MockVideoCaptureImpl() {}
+
+    MOCK_METHOD1(Send, void(IPC::Message* message));
+  };
+
   VideoCaptureImplTest() {
     message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
     message_loop_proxy_ =
@@ -62,8 +72,9 @@
     message_filter_ = new MockVideoCaptureMessageFilter;
     session_id_ = 1;
 
-    video_capture_impl_ = new VideoCaptureImpl(session_id_, message_loop_proxy_,
-                                               message_filter_);
+    video_capture_impl_ = new MockVideoCaptureImpl(session_id_,
+                                                   message_loop_proxy_,
+                                                   message_filter_);
 
     video_capture_impl_->device_id_ = 2;
   }
@@ -77,7 +88,7 @@
   scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
   scoped_refptr<MockVideoCaptureMessageFilter> message_filter_;
   media::VideoCaptureSessionId session_id_;
-  VideoCaptureImpl* video_capture_impl_;
+  MockVideoCaptureImpl* video_capture_impl_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest);
@@ -89,11 +100,8 @@
   scoped_ptr<MockVideoCaptureClient> client(new MockVideoCaptureClient);
   media::VideoCapture::VideoCaptureCapability capability = DEFAULT_CAPABILITY;
 
-  EXPECT_CALL(*message_filter_, Send(_))
-      .WillRepeatedly(DeleteMessage(true));
-
-  EXPECT_CALL(*message_filter_, ReadyToSend())
-      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*video_capture_impl_, Send(_))
+      .WillRepeatedly(DeleteMessage());
 
   EXPECT_CALL(*client, OnStarted(_))
       .WillOnce(Return());
diff --git a/content/renderer/render_thread.cc b/content/renderer/render_thread.cc
index c251a80..07e4867 100644
--- a/content/renderer/render_thread.cc
+++ b/content/renderer/render_thread.cc
@@ -44,6 +44,8 @@
 #include "content/renderer/render_view_visitor.h"
 #include "content/renderer/renderer_webidbfactory_impl.h"
 #include "content/renderer/renderer_webkitclient_impl.h"
+#include "content/renderer/video_capture_message_filter.h"
+#include "content/renderer/video_capture_message_filter_creator.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_platform_file.h"
 #include "net/base/net_errors.h"
@@ -167,6 +169,10 @@
   db_message_filter_ = new DBMessageFilter();
   AddFilter(db_message_filter_.get());
 
+  VideoCaptureMessageFilter* video_capture_message_filter =
+      VideoCaptureMessageFilterCreator::SharedFilter();
+  AddFilter(video_capture_message_filter);
+
   content::GetContentClient()->renderer()->RenderThreadStarted();
 
   TRACE_EVENT_END_ETW("RenderThread::Init", 0, "");
@@ -184,6 +190,10 @@
   RemoveFilter(db_message_filter_.get());
   db_message_filter_ = NULL;
 
+  VideoCaptureMessageFilter* video_capture_message_filter =
+      VideoCaptureMessageFilterCreator::SharedFilter();
+  RemoveFilter(video_capture_message_filter);
+
   // Shutdown the file thread if it's running.
   if (file_thread_.get())
     file_thread_->Stop();
diff --git a/content/renderer/video_capture_message_filter.cc b/content/renderer/video_capture_message_filter.cc
index f9db7e5..05ca8bb 100644
--- a/content/renderer/video_capture_message_filter.cc
+++ b/content/renderer/video_capture_message_filter.cc
@@ -4,8 +4,8 @@
 
 #include "content/renderer/video_capture_message_filter.h"
 
-#include "content/common/child_process.h"
 #include "content/common/video_capture_messages.h"
+#include "content/common/view_messages.h"
 #include "content/renderer/render_thread.h"
 
 VideoCaptureMessageFilter::VideoCaptureMessageFilter(int32 route_id)
@@ -23,14 +23,6 @@
     return false;
   }
 
-  if (!message_loop_proxy_->BelongsToCurrentThread()) {
-    // Can only access the IPC::Channel on the IPC thread since it's not thread
-    // safe.
-    message_loop_proxy_->PostTask(FROM_HERE,
-        NewRunnableMethod(this, &VideoCaptureMessageFilter::Send, message));
-    return true;
-  }
-
   message->set_routing_id(route_id_);
   return channel_->Send(message);
 }
@@ -152,13 +144,3 @@
   }
 }
 
-void VideoCaptureMessageFilter::AddFilter() {
-  if (MessageLoop::current() != ChildThread::current()->message_loop()) {
-    ChildThread::current()->message_loop()->PostTask(
-      FROM_HERE, NewRunnableMethod(this,
-                                   &VideoCaptureMessageFilter::AddFilter));
-    return;
-  }
-
-  RenderThread::current()->AddFilter(this);
-}
diff --git a/content/renderer/video_capture_message_filter.h b/content/renderer/video_capture_message_filter.h
index c4766164..7ca67be 100644
--- a/content/renderer/video_capture_message_filter.h
+++ b/content/renderer/video_capture_message_filter.h
@@ -54,8 +54,6 @@
   // Send a message asynchronously.
   virtual bool Send(IPC::Message* message);
 
-  void AddFilter();
-
  private:
   FRIEND_TEST_ALL_PREFIXES(VideoCaptureMessageFilterTest, Basic);
   FRIEND_TEST_ALL_PREFIXES(VideoCaptureMessageFilterTest, Delegates);
diff --git a/content/renderer/video_capture_message_filter_creator.cc b/content/renderer/video_capture_message_filter_creator.cc
new file mode 100644
index 0000000..8535f34
--- /dev/null
+++ b/content/renderer/video_capture_message_filter_creator.cc
@@ -0,0 +1,26 @@
+// 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/video_capture_message_filter_creator.h"
+
+#include "content/renderer/video_capture_message_filter.h"
+
+VideoCaptureMessageFilterCreator::VideoCaptureMessageFilterCreator() {
+  filter_ = new VideoCaptureMessageFilter(1);
+}
+
+VideoCaptureMessageFilterCreator::~VideoCaptureMessageFilterCreator() {
+}
+
+// static
+VideoCaptureMessageFilter* VideoCaptureMessageFilterCreator::SharedFilter() {
+  return GetInstance()->filter_.get();
+}
+
+// static
+VideoCaptureMessageFilterCreator*
+    VideoCaptureMessageFilterCreator::GetInstance() {
+      return Singleton<VideoCaptureMessageFilterCreator>::get();
+}
+
diff --git a/content/renderer/video_capture_message_filter_creator.h b/content/renderer/video_capture_message_filter_creator.h
new file mode 100644
index 0000000..149dd744
--- /dev/null
+++ b/content/renderer/video_capture_message_filter_creator.h
@@ -0,0 +1,35 @@
+// 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_VIDEO_CAPTURE_MESSAGE_FILTER_CREATOR_H_
+#define CONTENT_RENDERER_VIDEO_CAPTURE_MESSAGE_FILTER_CREATOR_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+
+class VideoCaptureMessageFilter;
+
+// VideoCaptureMessageFilterCreator is to be used as a singleton so we can get
+// access to a shared VideoCaptureMessageFilter.
+// Example usage:
+//   VideoCaptureMessageFilter* filter =
+//       VideoCaptureMessageFilterCreator::SharedFilter();
+
+class VideoCaptureMessageFilterCreator {
+ public:
+  static VideoCaptureMessageFilter* SharedFilter();
+  static VideoCaptureMessageFilterCreator* GetInstance();
+
+ private:
+  VideoCaptureMessageFilterCreator();
+  ~VideoCaptureMessageFilterCreator();
+  friend struct DefaultSingletonTraits<VideoCaptureMessageFilterCreator>;
+
+  scoped_refptr<VideoCaptureMessageFilter> filter_;
+
+  DISALLOW_COPY_AND_ASSIGN(VideoCaptureMessageFilterCreator);
+};
+
+#endif  // CONTENT_RENDERER_VIDEO_CAPTURE_MESSAGE_FILTER_CREATOR_H_
+