summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-13 19:49:29 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-13 19:49:29 +0000
commit8be45847f76ec798c1241ed7e98cfb19f68b7e96 (patch)
tree7198fc01d68a1a5f4110c3167635f2000444054c /ppapi/proxy
parent43095f23d76d2ae3d50e1e8bb55c71152025d76c (diff)
downloadchromium_src-8be45847f76ec798c1241ed7e98cfb19f68b7e96.zip
chromium_src-8be45847f76ec798c1241ed7e98cfb19f68b7e96.tar.gz
chromium_src-8be45847f76ec798c1241ed7e98cfb19f68b7e96.tar.bz2
This adds a hang monitor for Pepper plugins. It monitors sync messages on the I/O thread of the renderer and sends a message to the browser if it's blocked for too long.
The browser will show an infobar allowing you to terminate the plugin. BUG=122795 Review URL: https://chromiumcodereview.appspot.com/10014013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132245 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r--ppapi/proxy/dispatcher.cc3
-rw-r--r--ppapi/proxy/dispatcher.h3
-rw-r--r--ppapi/proxy/host_dispatcher.cc13
-rw-r--r--ppapi/proxy/host_dispatcher.h27
-rw-r--r--ppapi/proxy/ppapi_proxy_test.cc17
-rw-r--r--ppapi/proxy/ppapi_proxy_test.h4
6 files changed, 57 insertions, 10 deletions
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
index a2a1d71..39b1a06 100644
--- a/ppapi/proxy/dispatcher.cc
+++ b/ppapi/proxy/dispatcher.cc
@@ -50,6 +50,9 @@ base::MessageLoopProxy* Dispatcher::GetIPCMessageLoop() {
void Dispatcher::AddIOThreadMessageFilter(
IPC::ChannelProxy::MessageFilter* filter) {
+ // Our filter is refcounted. The channel will call the destruct method on the
+ // filter when the channel is done with it, so the corresponding Release()
+ // happens there.
channel()->AddFilter(filter);
}
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h
index 35a82ab..df0f484 100644
--- a/ppapi/proxy/dispatcher.h
+++ b/ppapi/proxy/dispatcher.h
@@ -68,9 +68,6 @@ class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel {
base::MessageLoopProxy* GetIPCMessageLoop();
// Adds the given filter to the IO thread. Takes ownership of the pointer.
- // TODO(brettw) remove this. It's a hack to support the Flash
- // ModuleLocalThreadAdapter. When the thread stuff is sorted out, this
- // implementation detail should be hidden.
void AddIOThreadMessageFilter(IPC::ChannelProxy::MessageFilter* filter);
// TODO(brettw): What is this comment referring to?
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
index d1c28f7..9256fe9 100644
--- a/ppapi/proxy/host_dispatcher.cc
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -63,8 +63,10 @@ class BoolRestorer {
HostDispatcher::HostDispatcher(base::ProcessHandle remote_process_handle,
PP_Module module,
- GetInterfaceFunc local_get_interface)
+ GetInterfaceFunc local_get_interface,
+ SyncMessageStatusReceiver* sync_status)
: Dispatcher(remote_process_handle, local_get_interface),
+ sync_status_(sync_status),
pp_module_(module),
ppb_proxy_(NULL),
allow_plugin_reentrancy_(false) {
@@ -92,6 +94,8 @@ bool HostDispatcher::InitHostWithChannel(
const ppapi::Preferences& preferences) {
if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
return false;
+ AddIOThreadMessageFilter(sync_status_.get());
+
Send(new PpapiMsg_SetPreferences(preferences));
return true;
}
@@ -152,7 +156,12 @@ bool HostDispatcher::Send(IPC::Message* msg) {
// waiting for the reply, dispatches an incoming ExecuteScript call which
// destroys the plugin module and in turn the dispatcher.
ScopedModuleReference scoped_ref(this);
- return Dispatcher::Send(msg);
+
+ sync_status_->BeginBlockOnSyncMessage();
+ bool result = Dispatcher::Send(msg);
+ sync_status_->EndBlockOnSyncMessage();
+
+ return result;
} else {
// We don't want to have a scoped ref for async message cases since since
// async messages are sent during module desruction. In this case, the
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
index 1bacdfa..2d44979 100644
--- a/ppapi/proxy/host_dispatcher.h
+++ b/ppapi/proxy/host_dispatcher.h
@@ -9,8 +9,10 @@
#include <string>
#include <vector>
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/process.h"
+#include "ipc/ipc_channel_proxy.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/dispatcher.h"
#include "ppapi/shared_impl/function_group_base.h"
@@ -25,12 +27,31 @@ namespace proxy {
class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher {
public:
- // Constructor for the renderer side.
+ // This interface receives notifications about sync messages being sent by
+ // the dispatcher to the plugin process. It is used to detect a hung plugin.
+ //
+ // Note that there can be nested sync messages, so the begin/end status
+ // actually represents a stack of blocking messages.
+ class SyncMessageStatusReceiver : public IPC::ChannelProxy::MessageFilter {
+ public:
+ virtual ~SyncMessageStatusReceiver() {}
+
+ // Notification that a sync message is about to be sent out.
+ virtual void BeginBlockOnSyncMessage() = 0;
+
+ // Notification that a sync message reply was received and the dispatcher
+ // is no longer blocked on a sync message.
+ virtual void EndBlockOnSyncMessage() = 0;
+ };
+
+ // Constructor for the renderer side. This will take a reference to the
+ // SyncMessageStatusReceiver.
//
// You must call InitHostWithChannel after the constructor.
HostDispatcher(base::ProcessHandle host_process_handle,
PP_Module module,
- GetInterfaceFunc local_get_interface);
+ GetInterfaceFunc local_get_interface,
+ SyncMessageStatusReceiver* sync_status);
~HostDispatcher();
// You must call this function before anything else. Returns true on success.
@@ -90,6 +111,8 @@ class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher {
const std::string& source,
const std::string& value);
+ scoped_refptr<SyncMessageStatusReceiver> sync_status_;
+
PP_Module pp_module_;
// Maps interface name to whether that interface is supported. If an interface
diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc
index 7bfacc5..98baafd 100644
--- a/ppapi/proxy/ppapi_proxy_test.cc
+++ b/ppapi/proxy/ppapi_proxy_test.cc
@@ -5,6 +5,7 @@
#include "ppapi/proxy/ppapi_proxy_test.h"
#include "base/bind.h"
+#include "base/compiler_specific.h"
#include "base/message_loop_proxy.h"
#include "base/observer_list.h"
#include "ipc/ipc_sync_channel.h"
@@ -240,8 +241,16 @@ void PluginProxyTest::TearDown() {
// HostProxyTestHarness --------------------------------------------------------
+class HostProxyTestHarness::MockSyncMessageStatusReceiver
+ : public HostDispatcher::SyncMessageStatusReceiver {
+ public:
+ virtual void BeginBlockOnSyncMessage() OVERRIDE {}
+ virtual void EndBlockOnSyncMessage() OVERRIDE {}
+};
+
HostProxyTestHarness::HostProxyTestHarness()
- : host_globals_(PpapiGlobals::ForTest()) {
+ : host_globals_(PpapiGlobals::ForTest()),
+ status_receiver_(new MockSyncMessageStatusReceiver) {
}
HostProxyTestHarness::~HostProxyTestHarness() {
@@ -257,7 +266,8 @@ void HostProxyTestHarness::SetUpHarness() {
host_dispatcher_.reset(new HostDispatcher(
base::Process::Current().handle(),
pp_module(),
- &MockGetInterface));
+ &MockGetInterface,
+ status_receiver_.get()));
host_dispatcher_->InitWithTestSink(&sink());
HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
}
@@ -274,7 +284,8 @@ void HostProxyTestHarness::SetUpHarnessWithChannel(
host_dispatcher_.reset(new HostDispatcher(
base::Process::Current().handle(),
pp_module(),
- &MockGetInterface));
+ &MockGetInterface,
+ status_receiver_.get()));
ppapi::Preferences preferences;
host_dispatcher_->InitHostWithChannel(&delegate_mock_, channel_handle,
is_client, preferences);
diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h
index 6278f71..b2a3f36 100644
--- a/ppapi/proxy/ppapi_proxy_test.h
+++ b/ppapi/proxy/ppapi_proxy_test.h
@@ -198,9 +198,13 @@ class HostProxyTestHarness : public ProxyTestHarnessBase {
};
private:
+ class MockSyncMessageStatusReceiver;
+
ppapi::TestGlobals host_globals_;
scoped_ptr<HostDispatcher> host_dispatcher_;
DelegateMock delegate_mock_;
+
+ scoped_ptr<MockSyncMessageStatusReceiver> status_receiver_;
};
class HostProxyTest : public HostProxyTestHarness, public testing::Test {