summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/nacl_host/nacl_browser_delegate_impl.cc82
-rw-r--r--chrome/browser/nacl_host/nacl_browser_delegate_impl.h2
-rw-r--r--components/nacl/browser/nacl_browser_delegate.h9
-rw-r--r--components/nacl/browser/nacl_process_host.cc3
-rw-r--r--components/nacl/browser/test_nacl_browser_delegate.cc5
-rw-r--r--components/nacl/browser/test_nacl_browser_delegate.h2
-rw-r--r--content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc58
-rw-r--r--content/browser/renderer_host/pepper/browser_ppapi_host_impl.h20
-rw-r--r--content/public/browser/browser_ppapi_host.h15
-rw-r--r--extensions/browser/process_manager.cc2
-rw-r--r--ppapi/proxy/plugin_globals.cc47
-rw-r--r--ppapi/proxy/plugin_globals.h21
-rw-r--r--ppapi/proxy/ppapi_messages.h3
-rw-r--r--ppapi/shared_impl/ppapi_globals.cc3
-rw-r--r--ppapi/shared_impl/ppapi_globals.h6
-rw-r--r--ppapi/thunk/enter.cc5
16 files changed, 268 insertions, 15 deletions
diff --git a/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc b/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc
index a0e92bd..96e0c1f 100644
--- a/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc
+++ b/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc
@@ -9,15 +9,20 @@
#include "base/strings/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/nacl_host/nacl_infobar_delegate.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/logging_chrome.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
#include "extensions/browser/info_map.h"
+#include "extensions/browser/process_manager.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
@@ -26,6 +31,78 @@
using extensions::SharedModuleInfo;
+namespace {
+
+// Handles an extension's NaCl process transitioning in or out of idle state by
+// relaying the state to the extension's process manager.
+//
+// A NaCl instance, when active (making PPAPI calls or receiving callbacks),
+// sends keepalive IPCs to the browser process BrowserPpapiHost at a throttled
+// rate. The content::BrowserPpapiHost passes context information up to the
+// chrome level NaClProcessHost where we use the instance's context to find the
+// associated extension process manager.
+//
+// There is a 1:many relationship for extension:nacl-embeds, but only a
+// 1:1 relationship for NaClProcessHost:PP_Instance. The content layer doesn't
+// rely on this knowledge because it routes messages for ppapi non-nacl
+// instances as well, though they won't have callbacks set. Here the 1:1
+// assumption is made and DCHECKed.
+void OnKeepaliveOnUIThread(
+ const content::BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
+ const base::FilePath& profile_data_directory) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ // Only one instance will exist for NaCl embeds, even when more than one
+ // embed of the same plugin exists on the same page.
+ DCHECK(instance_data.size() == 1);
+ if (instance_data.size() < 1)
+ return;
+
+ content::RenderViewHost* render_view_host = content::RenderViewHost::FromID(
+ instance_data[0].render_process_id, instance_data[0].render_view_id);
+ if (!render_view_host)
+ return;
+
+ content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
+ if (!site_instance)
+ return;
+
+ extensions::ExtensionSystem* extension_system =
+ extensions::ExtensionSystem::GetForBrowserContext(
+ site_instance->GetBrowserContext());
+ if (!extension_system)
+ return;
+
+ const ExtensionService* extension_service =
+ extension_system->extension_service();
+ if (!extension_service)
+ return;
+
+ const extensions::Extension* extension = extension_service->GetExtensionById(
+ instance_data[0].document_url.host(), false);
+ if (!extension)
+ return;
+
+ extensions::ProcessManager* pm = extension_system->process_manager();
+ if (!pm)
+ return;
+
+ pm->KeepaliveImpulse(extension);
+}
+
+// Calls OnKeepaliveOnUIThread on UI thread.
+void OnKeepalive(
+ const content::BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
+ const base::FilePath& profile_data_directory) {
+ DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&OnKeepaliveOnUIThread,
+ instance_data,
+ profile_data_directory));
+}
+
+} // namespace
+
NaClBrowserDelegateImpl::NaClBrowserDelegateImpl(
extensions::InfoMap* extension_info_map)
: extension_info_map_(extension_info_map), inverse_debug_patterns_(false) {}
@@ -181,3 +258,8 @@ bool NaClBrowserDelegateImpl::MapUrlToLocalFilePath(
*file_path = resource_file_path;
return true;
}
+
+content::BrowserPpapiHost::OnKeepaliveCallback
+NaClBrowserDelegateImpl::GetOnKeepaliveCallback() {
+ return base::Bind(&OnKeepalive);
+}
diff --git a/chrome/browser/nacl_host/nacl_browser_delegate_impl.h b/chrome/browser/nacl_host/nacl_browser_delegate_impl.h
index c23fefc..674d517 100644
--- a/chrome/browser/nacl_host/nacl_browser_delegate_impl.h
+++ b/chrome/browser/nacl_host/nacl_browser_delegate_impl.h
@@ -29,6 +29,8 @@ class NaClBrowserDelegateImpl : public NaClBrowserDelegate {
base::FilePath* file_path) OVERRIDE;
virtual void SetDebugPatterns(std::string debug_patterns) OVERRIDE;
virtual bool URLMatchesDebugPatterns(const GURL& manifest_url) OVERRIDE;
+ virtual content::BrowserPpapiHost::OnKeepaliveCallback
+ GetOnKeepaliveCallback() OVERRIDE;
private:
scoped_refptr<extensions::InfoMap> extension_info_map_;
diff --git a/components/nacl/browser/nacl_browser_delegate.h b/components/nacl/browser/nacl_browser_delegate.h
index 0540f60..30bf467 100644
--- a/components/nacl/browser/nacl_browser_delegate.h
+++ b/components/nacl/browser/nacl_browser_delegate.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/callback_forward.h"
+#include "content/public/browser/browser_ppapi_host.h"
class GURL;
@@ -21,10 +22,6 @@ class HostFactory;
}
}
-namespace content {
-class BrowserPpapiHost;
-}
-
// Encapsulates the dependencies of NaCl code on chrome/, to avoid a direct
// dependency on chrome/.
class NaClBrowserDelegate {
@@ -73,6 +70,10 @@ class NaClBrowserDelegate {
// Returns whether NaCl application with this manifest URL should be debugged.
virtual bool URLMatchesDebugPatterns(const GURL& manifest_url) = 0;
+
+ // Returns a callback that handles NaCl idle state transitions.
+ virtual content::BrowserPpapiHost::OnKeepaliveCallback
+ GetOnKeepaliveCallback() = 0;
};
#endif // COMPONENTS_NACL_BROWSER_NACL_BROWSER_DELEGATE_H_
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 2d154f3..a0868b8 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -49,6 +49,7 @@
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppapi_nacl_channel_args.h"
+#include "ppapi/shared_impl/ppapi_switches.h"
#if defined(OS_POSIX)
#include <fcntl.h>
@@ -799,6 +800,8 @@ void NaClProcessHost::OnPpapiChannelCreated(
nacl_host_message_filter_->render_process_id(),
render_view_id_,
profile_directory_));
+ ppapi_host_->SetOnKeepaliveCallback(
+ NaClBrowser::GetDelegate()->GetOnKeepaliveCallback());
ppapi::PpapiNaClChannelArgs args;
args.off_the_record = nacl_host_message_filter_->off_the_record();
diff --git a/components/nacl/browser/test_nacl_browser_delegate.cc b/components/nacl/browser/test_nacl_browser_delegate.cc
index 2cd0bba..d0b5607 100644
--- a/components/nacl/browser/test_nacl_browser_delegate.cc
+++ b/components/nacl/browser/test_nacl_browser_delegate.cc
@@ -53,3 +53,8 @@ bool TestNaClBrowserDelegate::URLMatchesDebugPatterns(
const GURL& manifest_url) {
return false;
}
+
+content::BrowserPpapiHost::OnKeepaliveCallback
+TestNaClBrowserDelegate::GetOnKeepaliveCallback() {
+ return content::BrowserPpapiHost::OnKeepaliveCallback();
+}
diff --git a/components/nacl/browser/test_nacl_browser_delegate.h b/components/nacl/browser/test_nacl_browser_delegate.h
index fc0444f..2e8e5f6 100644
--- a/components/nacl/browser/test_nacl_browser_delegate.h
+++ b/components/nacl/browser/test_nacl_browser_delegate.h
@@ -38,6 +38,8 @@ class TestNaClBrowserDelegate : public NaClBrowserDelegate {
base::FilePath* file_path) OVERRIDE;
virtual void SetDebugPatterns(std::string debug_patterns) OVERRIDE;
virtual bool URLMatchesDebugPatterns(const GURL& manifest_url) OVERRIDE;
+ virtual content::BrowserPpapiHost::OnKeepaliveCallback
+ GetOnKeepaliveCallback() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(TestNaClBrowserDelegate);
diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index c3c2c6f3..fd2c82e 100644
--- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -7,9 +7,9 @@
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/common/pepper_renderer_instance_data.h"
-#include "content/public/browser/render_view_host.h"
#include "content/public/common/process_type.h"
#include "ipc/ipc_message_macros.h"
+#include "ppapi/proxy/ppapi_messages.h"
namespace content {
@@ -55,7 +55,7 @@ BrowserPpapiHostImpl::BrowserPpapiHostImpl(
in_process_(in_process),
external_plugin_(external_plugin),
ssl_context_helper_(new SSLContextHelper()) {
- message_filter_ = new HostMessageFilter(ppapi_host_.get());
+ message_filter_ = new HostMessageFilter(ppapi_host_.get(), this);
ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
new ContentBrowserPepperHostFactory(this)));
}
@@ -126,6 +126,11 @@ GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) {
return found->second.plugin_url;
}
+void BrowserPpapiHostImpl::SetOnKeepaliveCallback(
+ const BrowserPpapiHost::OnKeepaliveCallback& callback) {
+ on_keepalive_callback_ = callback;
+}
+
void BrowserPpapiHostImpl::AddInstance(
PP_Instance instance,
const PepperRendererInstanceData& instance_data) {
@@ -142,26 +147,67 @@ void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) {
instance_map_.erase(found);
}
+BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter(
+ ppapi::host::PpapiHost* ppapi_host,
+ BrowserPpapiHostImpl* browser_ppapi_host_impl)
+ : ppapi_host_(ppapi_host),
+ browser_ppapi_host_impl_(browser_ppapi_host_impl) {
+}
+
bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived(
const IPC::Message& msg) {
// Don't forward messages if our owner object has been destroyed.
if (!ppapi_host_)
return false;
- /* TODO(brettw) when we add messages, here, the code should look like this:
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl, msg)
+ IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter, msg)
// Add necessary message handlers here.
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_Keepalive, OnKeepalive)
IPC_MESSAGE_UNHANDLED(handled = ppapi_host_->OnMessageReceived(msg))
IPC_END_MESSAGE_MAP();
return handled;
- */
- return ppapi_host_->OnMessageReceived(msg);
}
void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
DCHECK(ppapi_host_);
ppapi_host_ = NULL;
+ browser_ppapi_host_impl_ = NULL;
+}
+
+BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {
+}
+
+void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() {
+ if (browser_ppapi_host_impl_)
+ browser_ppapi_host_impl_->OnKeepalive();
+}
+
+void BrowserPpapiHostImpl::OnKeepalive() {
+ // An instance has been active. The on_keepalive_callback_ will be
+ // used to permit the content embedder to handle this, e.g. by tracking
+ // activity and shutting down processes that go idle.
+ //
+ // Currently embedders do not need to distinguish between instances having
+ // different idle state, and thus this implementation handles all instances
+ // for this module together.
+
+ if (on_keepalive_callback_.is_null())
+ return;
+
+ BrowserPpapiHost::OnKeepaliveInstanceData
+ instance_data(instance_map_.size());
+
+ InstanceMap::iterator instance = instance_map_.begin();
+ int i = 0;
+ while (instance != instance_map_.end()) {
+ instance_data[i].render_process_id = instance->second.render_process_id;
+ instance_data[i].render_view_id = instance->second.render_view_id;
+ instance_data[i].document_url = instance->second.document_url;
+ ++instance;
+ ++i;
+ }
+ on_keepalive_callback_.Run(instance_data, profile_data_directory_);
}
} // namespace content
diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
index 5d95342..d987bd4 100644
--- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
+++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "content/common/content_export.h"
@@ -52,6 +53,9 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
virtual const base::FilePath& GetProfileDataDirectory() OVERRIDE;
virtual GURL GetDocumentURLForInstance(PP_Instance instance) OVERRIDE;
virtual GURL GetPluginURLForInstance(PP_Instance instance) OVERRIDE;
+ virtual void SetOnKeepaliveCallback(
+ const BrowserPpapiHost::OnKeepaliveCallback& callback) OVERRIDE;
+
void set_plugin_process_handle(base::ProcessHandle handle) {
plugin_process_handle_ = handle;
@@ -83,19 +87,27 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
// reference. To avoid that, define a message filter object.
class HostMessageFilter : public IPC::ChannelProxy::MessageFilter {
public:
- explicit HostMessageFilter(ppapi::host::PpapiHost* ppapi_host)
- : ppapi_host_(ppapi_host) {}
+ HostMessageFilter(ppapi::host::PpapiHost* ppapi_host,
+ BrowserPpapiHostImpl* browser_ppapi_host_impl);
+
// IPC::ChannelProxy::MessageFilter.
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
void OnHostDestroyed();
private:
- virtual ~HostMessageFilter() {}
+ virtual ~HostMessageFilter();
+
+ void OnKeepalive();
+ // Non owning pointers cleared in OnHostDestroyed()
ppapi::host::PpapiHost* ppapi_host_;
+ BrowserPpapiHostImpl* browser_ppapi_host_impl_;
};
+ // Reports plugin activity to the callback set with SetOnKeepaliveCallback.
+ void OnKeepalive();
+
scoped_ptr<ppapi::host::PpapiHost> ppapi_host_;
base::ProcessHandle plugin_process_handle_;
std::string plugin_name_;
@@ -118,6 +130,8 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
scoped_refptr<HostMessageFilter> message_filter_;
+ BrowserPpapiHost::OnKeepaliveCallback on_keepalive_callback_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserPpapiHostImpl);
};
diff --git a/content/public/browser/browser_ppapi_host.h b/content/public/browser/browser_ppapi_host.h
index 45f997e..ce76d16 100644
--- a/content/public/browser/browser_ppapi_host.h
+++ b/content/public/browser/browser_ppapi_host.h
@@ -34,6 +34,17 @@ namespace content {
// lives entirely on the I/O thread.
class CONTENT_EXPORT BrowserPpapiHost {
public:
+ struct OnKeepaliveInstanceStruct {
+ int render_process_id;
+ int render_view_id;
+ GURL document_url;
+ };
+ typedef std::vector<OnKeepaliveInstanceStruct> OnKeepaliveInstanceData;
+ typedef base::Callback<
+ void (const OnKeepaliveInstanceData& instance_data,
+ const base::FilePath& profile_data_directory)>
+ OnKeepaliveCallback;
+
// Creates a browser host and sets up an out-of-process proxy for an external
// pepper plugin process.
static BrowserPpapiHost* CreateExternalPluginProcess(
@@ -81,6 +92,10 @@ class CONTENT_EXPORT BrowserPpapiHost {
// Get the Document/Plugin URLs for the given PP_Instance.
virtual GURL GetDocumentURLForInstance(PP_Instance instance) = 0;
virtual GURL GetPluginURLForInstance(PP_Instance instance) = 0;
+
+ // Sets a callback the BrowserPpapiHost will run when the plugin messages
+ // that it is active.
+ virtual void SetOnKeepaliveCallback(const OnKeepaliveCallback& callback) = 0;
};
} // namespace content
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 6a57d8e..e49d990 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -203,6 +203,8 @@ ProcessManager::ProcessManager(BrowserContext* context,
content::Source<BrowserContext>(original_context));
}
+ // Note: event_page_idle_time_ must be sufficiently larger (e.g. 2x) than
+ // kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals.
event_page_idle_time_ = base::TimeDelta::FromSeconds(10);
unsigned idle_time_msec = 0;
if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
diff --git a/ppapi/proxy/plugin_globals.cc b/ppapi/proxy/plugin_globals.cc
index 59b5191..d34adf1 100644
--- a/ppapi/proxy/plugin_globals.cc
+++ b/ppapi/proxy/plugin_globals.cc
@@ -10,11 +10,18 @@
#include "ipc/ipc_sender.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_proxy_delegate.h"
+#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_message_loop_proxy.h"
#include "ppapi/proxy/resource_reply_thread_registrar.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/thunk/enter.h"
+namespace {
+
+const int kKeepaliveThrottleIntervalDefault = 5000;
+
+} // namespace
+
namespace ppapi {
namespace proxy {
@@ -54,7 +61,11 @@ PluginGlobals::PluginGlobals()
plugin_proxy_delegate_(NULL),
callback_tracker_(new CallbackTracker),
resource_reply_thread_registrar_(
- new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) {
+ new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
+ plugin_recently_active_(false),
+ keepalive_throttle_interval_milliseconds_(
+ kKeepaliveThrottleIntervalDefault),
+ weak_factory_(this) {
DCHECK(!plugin_globals_);
plugin_globals_ = this;
@@ -71,7 +82,11 @@ PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test)
plugin_proxy_delegate_(NULL),
callback_tracker_(new CallbackTracker),
resource_reply_thread_registrar_(
- new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) {
+ new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
+ plugin_recently_active_(false),
+ keepalive_throttle_interval_milliseconds_(
+ kKeepaliveThrottleIntervalDefault),
+ weak_factory_(this) {
DCHECK(!plugin_globals_);
}
@@ -165,6 +180,21 @@ base::TaskRunner* PluginGlobals::GetFileTaskRunner() {
return file_thread_->message_loop_proxy();
}
+void PluginGlobals::MarkPluginIsActive() {
+ if (!plugin_recently_active_) {
+ plugin_recently_active_ = true;
+ if (!GetBrowserSender() || !base::MessageLoop::current())
+ return;
+ GetBrowserSender()->Send(new PpapiHostMsg_Keepalive());
+
+ GetMainThreadMessageLoop()->PostDelayedTask(FROM_HERE,
+ RunWhileLocked(base::Bind(&PluginGlobals::OnReleaseKeepaliveThrottle,
+ weak_factory_.GetWeakPtr())),
+ base::TimeDelta::FromMilliseconds(
+ keepalive_throttle_interval_milliseconds()));
+ }
+}
+
IPC::Sender* PluginGlobals::GetBrowserSender() {
if (!browser_sender_.get()) {
browser_sender_.reset(
@@ -195,9 +225,22 @@ MessageLoopResource* PluginGlobals::loop_for_main_thread() {
return loop_for_main_thread_.get();
}
+int PluginGlobals::keepalive_throttle_interval_milliseconds() const {
+ return keepalive_throttle_interval_milliseconds_;
+}
+
+void PluginGlobals::set_keepalive_throttle_interval_milliseconds(int i) {
+ keepalive_throttle_interval_milliseconds_ = i;
+}
+
bool PluginGlobals::IsPluginGlobals() const {
return true;
}
+void PluginGlobals::OnReleaseKeepaliveThrottle() {
+ ppapi::ProxyLock::AssertAcquiredDebugOnly();
+ plugin_recently_active_ = false;
+}
+
} // namespace proxy
} // namespace ppapi
diff --git a/ppapi/proxy/plugin_globals.h b/ppapi/proxy/plugin_globals.h
index 029e2d2..dac33b6 100644
--- a/ppapi/proxy/plugin_globals.h
+++ b/ppapi/proxy/plugin_globals.h
@@ -74,6 +74,7 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals {
const std::string& value) OVERRIDE;
virtual MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
base::TaskRunner* GetFileTaskRunner() OVERRIDE;
+ virtual void MarkPluginIsActive() OVERRIDE;
// Returns the channel for sending to the browser.
IPC::Sender* GetBrowserSender();
@@ -133,12 +134,21 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals {
return resource_reply_thread_registrar_.get();
}
+ // Interval to limit how many IPC messages are sent indicating that the plugin
+ // is active and should be kept alive. The value must be smaller than any
+ // threshold used to kill inactive plugins by the embedder host.
+ int keepalive_throttle_interval_milliseconds() const;
+ void set_keepalive_throttle_interval_milliseconds(int i);
+
private:
class BrowserSender;
// PpapiGlobals overrides.
virtual bool IsPluginGlobals() const OVERRIDE;
+ // Locks the proxy lock and releases the throttle on keepalive IPC messages.
+ void OnReleaseKeepaliveThrottle();
+
static PluginGlobals* plugin_globals_;
PluginProxyDelegate* plugin_proxy_delegate_;
@@ -167,6 +177,17 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals {
scoped_refptr<ResourceReplyThreadRegistrar> resource_reply_thread_registrar_;
+ // Indicates activity by the plugin. Used to monitor when a plugin can be
+ // shutdown due to idleness. Current needs do not require differentiating
+ // between idle state between multiple instances, if any are active they are
+ // all considered active.
+ bool plugin_recently_active_;
+
+ int keepalive_throttle_interval_milliseconds_;
+
+ // Member variables should appear before the WeakPtrFactory, see weak_ptr.h.
+ base::WeakPtrFactory<PluginGlobals> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PluginGlobals);
};
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 4b4fed8..086d42a 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -726,6 +726,9 @@ IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError,
PP_VideoDecodeError_Dev /* error */)
#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+// Reports to the browser that a plugin has been active.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Keepalive)
+
// -----------------------------------------------------------------------------
// These are from the plugin to the renderer.
diff --git a/ppapi/shared_impl/ppapi_globals.cc b/ppapi/shared_impl/ppapi_globals.cc
index 28ed2cf..f652f15 100644
--- a/ppapi/shared_impl/ppapi_globals.cc
+++ b/ppapi/shared_impl/ppapi_globals.cc
@@ -69,6 +69,9 @@ bool PpapiGlobals::IsPluginGlobals() const {
return false;
}
+void PpapiGlobals::MarkPluginIsActive() {
+}
+
// static
PpapiGlobals* PpapiGlobals::GetThreadLocalPointer() {
return tls_ppapi_globals_for_test.Pointer()->Get();
diff --git a/ppapi/shared_impl/ppapi_globals.h b/ppapi/shared_impl/ppapi_globals.h
index 93ab299..d9be0387 100644
--- a/ppapi/shared_impl/ppapi_globals.h
+++ b/ppapi/shared_impl/ppapi_globals.h
@@ -128,6 +128,12 @@ class PPAPI_SHARED_EXPORT PpapiGlobals {
virtual bool IsHostGlobals() const;
virtual bool IsPluginGlobals() const;
+ // Records that the plugin is active. The plugin reports that it is active to
+ // containers that monitor and shutdown idle content such as background apps.
+ // This method only has an effect on the plugin process, calls from the
+ // renderer process will have no effect.
+ virtual void MarkPluginIsActive();
+
private:
// Return the thread-local pointer which is used only for unit testing. It
// should always be NULL when running in production. It allows separate
diff --git a/ppapi/thunk/enter.cc b/ppapi/thunk/enter.cc
index 47889dd..2adc7f2 100644
--- a/ppapi/thunk/enter.cc
+++ b/ppapi/thunk/enter.cc
@@ -32,16 +32,19 @@ namespace subtle {
EnterBase::EnterBase()
: resource_(NULL),
retval_(PP_OK) {
+ PpapiGlobals::Get()->MarkPluginIsActive();
}
EnterBase::EnterBase(PP_Resource resource)
: resource_(GetResource(resource)),
retval_(PP_OK) {
+ PpapiGlobals::Get()->MarkPluginIsActive();
}
EnterBase::EnterBase(PP_Instance instance, SingletonResourceID resource_id)
: resource_(GetSingletonResource(instance, resource_id)),
retval_(PP_OK) {
+ PpapiGlobals::Get()->MarkPluginIsActive();
}
EnterBase::EnterBase(PP_Resource resource,
@@ -49,6 +52,7 @@ EnterBase::EnterBase(PP_Resource resource,
: resource_(GetResource(resource)),
retval_(PP_OK) {
callback_ = new TrackedCallback(resource_, callback);
+ PpapiGlobals::Get()->MarkPluginIsActive();
}
EnterBase::EnterBase(PP_Instance instance, SingletonResourceID resource_id,
@@ -59,6 +63,7 @@ EnterBase::EnterBase(PP_Instance instance, SingletonResourceID resource_id,
if (!resource_)
retval_ = PP_ERROR_BADARGUMENT;
callback_ = new TrackedCallback(resource_, callback);
+ PpapiGlobals::Get()->MarkPluginIsActive();
}
EnterBase::~EnterBase() {