diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-13 19:49:29 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-13 19:49:29 +0000 |
commit | 8be45847f76ec798c1241ed7e98cfb19f68b7e96 (patch) | |
tree | 7198fc01d68a1a5f4110c3167635f2000444054c /ppapi/proxy | |
parent | 43095f23d76d2ae3d50e1e8bb55c71152025d76c (diff) | |
download | chromium_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.cc | 3 | ||||
-rw-r--r-- | ppapi/proxy/dispatcher.h | 3 | ||||
-rw-r--r-- | ppapi/proxy/host_dispatcher.cc | 13 | ||||
-rw-r--r-- | ppapi/proxy/host_dispatcher.h | 27 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_proxy_test.cc | 17 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_proxy_test.h | 4 |
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 { |