summaryrefslogtreecommitdiffstats
path: root/webkit/plugins/ppapi
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-15 17:36:33 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-15 17:36:33 +0000
commit4f15d284466def720aa90d4f745edfa9af378094 (patch)
treee30ce116b0c05d4adacf9fa5aae6188178b4a3a7 /webkit/plugins/ppapi
parent351856ef135301f705435a8feecbc66ecfafbf77 (diff)
downloadchromium_src-4f15d284466def720aa90d4f745edfa9af378094.zip
chromium_src-4f15d284466def720aa90d4f745edfa9af378094.tar.gz
chromium_src-4f15d284466def720aa90d4f745edfa9af378094.tar.bz2
Implement basic crash detection and shutdown handling for out of process PPAPI
plugins. Currently when a crash is detected we just delete as much stuff as is convenient, clear the plugin's backing store, and continue running. It does not hook up a sad plugin page yet. This adds a "proxy" interface for the proxy to tell the PPAPI backend implementation in the renderer about proxy-related stuff (like the plugin crashing). This also implements keeping the process alive for a period of time so we can re-use the same process. Review URL: http://codereview.chromium.org/6493004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74965 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/plugins/ppapi')
-rw-r--r--webkit/plugins/ppapi/plugin_module.cc11
-rw-r--r--webkit/plugins/ppapi/plugin_module.h4
-rw-r--r--webkit/plugins/ppapi/ppapi_plugin_instance.cc12
-rw-r--r--webkit/plugins/ppapi/ppapi_plugin_instance.h3
-rw-r--r--webkit/plugins/ppapi/ppb_proxy_impl.cc34
-rw-r--r--webkit/plugins/ppapi/ppb_proxy_impl.h22
-rw-r--r--webkit/plugins/ppapi/resource_tracker.cc114
-rw-r--r--webkit/plugins/ppapi/resource_tracker.h10
8 files changed, 157 insertions, 53 deletions
diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc
index a8d804a..a99a29c 100644
--- a/webkit/plugins/ppapi/plugin_module.cc
+++ b/webkit/plugins/ppapi/plugin_module.cc
@@ -52,6 +52,7 @@
#include "ppapi/c/private/ppb_flash.h"
#include "ppapi/c/private/ppb_flash_menu.h"
#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/c/private/ppb_nacl_private.h"
#include "ppapi/c/trusted/ppb_image_data_trusted.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
@@ -74,6 +75,7 @@
#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
#include "webkit/plugins/ppapi/ppb_nacl_private_impl.h"
#include "webkit/plugins/ppapi/ppb_pdf_impl.h"
+#include "webkit/plugins/ppapi/ppb_proxy_impl.h"
#include "webkit/plugins/ppapi/ppb_scrollbar_impl.h"
#include "webkit/plugins/ppapi/ppb_transport_impl.h"
#include "webkit/plugins/ppapi/ppb_url_loader_impl.h"
@@ -260,6 +262,8 @@ const void* GetInterface(const char* name) {
return PluginInstance::GetInterface();
if (strcmp(name, PPB_PDF_INTERFACE) == 0)
return PPB_PDF_Impl::GetInterface();
+ if (strcmp(name, PPB_PROXY_PRIVATE_INTERFACE) == 0)
+ return PPB_Proxy_Impl::GetInterface();
if (strcmp(name, PPB_SCROLLBAR_DEV_INTERFACE) == 0)
return PPB_Scrollbar_Impl::GetInterface();
if (strcmp(name, PPB_TRANSPORT_DEV_INTERFACE) == 0)
@@ -472,6 +476,13 @@ scoped_refptr<CallbackTracker> PluginModule::GetCallbackTracker() {
return callback_tracker_;
}
+void PluginModule::PluginCrashed() {
+ // Notify all instances that they crashed.
+ for (PluginInstanceSet::iterator i = instances_.begin();
+ i != instances_.end(); ++i)
+ (*i)->InstanceCrashed();
+}
+
bool PluginModule::InitializeModule() {
DCHECK(!out_of_process_proxy_.get()) << "Don't call for proxied modules.";
int retval = entry_points_.initialize_module(pp_module(), &GetInterface);
diff --git a/webkit/plugins/ppapi/plugin_module.h b/webkit/plugins/ppapi/plugin_module.h
index 4f3e9c3..f21dbde 100644
--- a/webkit/plugins/ppapi/plugin_module.h
+++ b/webkit/plugins/ppapi/plugin_module.h
@@ -122,6 +122,10 @@ class PluginModule : public base::RefCounted<PluginModule>,
scoped_refptr<CallbackTracker> GetCallbackTracker();
+ // Called when running out of process and the plugin crashed. This will
+ // release relevant resources and update all affected instances.
+ void PluginCrashed();
+
private:
// Calls the InitializeModule entrypoint. The entrypoint must have been
// set and the plugin must not be out of process (we don't maintain
diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc
index ee815f3..421d676 100644
--- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc
+++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc
@@ -417,6 +417,18 @@ void PluginInstance::CommitBackingTexture() {
container_->commitBackingTexture();
}
+void PluginInstance::InstanceCrashed() {
+ // Force free all resources and vars.
+ ResourceTracker::Get()->InstanceCrashed(pp_instance());
+
+ // Free any associated graphics.
+ SetFullscreen(false);
+ bound_graphics_ = NULL;
+ InvalidateRect(gfx::Rect());
+
+ // TODO(brettw) show a crashed plugin screen.
+}
+
PP_Var PluginInstance::GetWindowObject() {
if (!container_)
return PP_MakeUndefined();
diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h
index b876d1d..c6ba2ec 100644
--- a/webkit/plugins/ppapi/ppapi_plugin_instance.h
+++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h
@@ -122,6 +122,9 @@ class PluginInstance : public base::RefCounted<PluginInstance> {
// rendering up to an offscreen SwapBuffers are visible.
void CommitBackingTexture();
+ // Called when the out-of-process plugin implementing this instance crashed.
+ void InstanceCrashed();
+
// PPB_Instance implementation.
PP_Var GetWindowObject();
PP_Var GetOwnerElementObject();
diff --git a/webkit/plugins/ppapi/ppb_proxy_impl.cc b/webkit/plugins/ppapi/ppb_proxy_impl.cc
new file mode 100644
index 0000000..f5a5102
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_proxy_impl.cc
@@ -0,0 +1,34 @@
+// 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 "webkit/plugins/ppapi/ppb_proxy_impl.h"
+
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "webkit/plugins/ppapi/plugin_module.h"
+#include "webkit/plugins/ppapi/resource_tracker.h"
+
+namespace webkit {
+namespace ppapi {
+
+namespace {
+
+void PluginCrashed(PP_Module module) {
+ PluginModule* plugin_module = ResourceTracker::Get()->GetModule(module);
+ if (plugin_module)
+ plugin_module->PluginCrashed();
+}
+
+const PPB_Proxy_Private ppb_proxy = {
+ &PluginCrashed
+};
+
+} // namespace
+
+// static
+const PPB_Proxy_Private* PPB_Proxy_Impl::GetInterface() {
+ return &ppb_proxy;
+}
+
+} // namespace ppapi
+} // namespace webkit
diff --git a/webkit/plugins/ppapi/ppb_proxy_impl.h b/webkit/plugins/ppapi/ppb_proxy_impl.h
new file mode 100644
index 0000000..72a333a
--- /dev/null
+++ b/webkit/plugins/ppapi/ppb_proxy_impl.h
@@ -0,0 +1,22 @@
+// 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 WEBKIT_PLUGINS_PPAPI_PPB_PROXY_IMPL_H_
+#define WEBKIT_PLUGINS_PPAPI_PPB_PROXY_IMPL_H_
+
+struct PPB_Proxy_Private;
+
+namespace webkit {
+namespace ppapi {
+
+class PPB_Proxy_Impl {
+ public:
+ static const PPB_Proxy_Private* GetInterface();
+};
+
+} // namespace ppapi
+} // namespace webkit
+
+#endif // WEBKIT_PLUGINS_PPAPI_PPB_PROXY_IMPL_H_
+
diff --git a/webkit/plugins/ppapi/resource_tracker.cc b/webkit/plugins/ppapi/resource_tracker.cc
index ed876d7..b17210c 100644
--- a/webkit/plugins/ppapi/resource_tracker.cc
+++ b/webkit/plugins/ppapi/resource_tracker.cc
@@ -159,6 +159,64 @@ bool ResourceTracker::UnrefResource(PP_Resource res) {
}
}
+void ResourceTracker::CleanupInstanceData(PP_Instance instance,
+ bool delete_instance) {
+ DLOG_IF(ERROR, !CheckIdType(instance, PP_ID_TYPE_INSTANCE))
+ << instance << " is not a PP_Instance.";
+ InstanceMap::iterator found = instance_map_.find(instance);
+ if (found == instance_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+ InstanceData& data = found->second;
+
+ // Force release all plugin references to resources associated with the
+ // deleted instance.
+ ResourceSet::iterator cur_res = data.resources.begin();
+ while (cur_res != data.resources.end()) {
+ ResourceMap::iterator found_resource = live_resources_.find(*cur_res);
+ if (found_resource == live_resources_.end()) {
+ NOTREACHED();
+ } else {
+ Resource* resource = found_resource->second.first;
+
+ // Must delete from the resource set first since the resource's instance
+ // pointer will get zeroed out in LastPluginRefWasDeleted.
+ resource->LastPluginRefWasDeleted(true);
+ live_resources_.erase(*cur_res);
+ }
+
+ // Iterators to a set are stable so we can iterate the set while the items
+ // are being deleted as long as we're careful not to delete the item we're
+ // holding an iterator to.
+ ResourceSet::iterator current = cur_res++;
+ data.resources.erase(current);
+ }
+ DCHECK(data.resources.empty());
+
+ // Force delete all var references.
+ VarSet::iterator cur_var = data.object_vars.begin();
+ while (cur_var != data.object_vars.end()) {
+ VarSet::iterator current = cur_var++;
+
+ // Tell the corresponding ObjectVar that the instance is gone.
+ PP_Var object_pp_var;
+ object_pp_var.type = PP_VARTYPE_OBJECT;
+ object_pp_var.value.as_id = *current;
+ scoped_refptr<ObjectVar> object_var(ObjectVar::FromPPVar(object_pp_var));
+ if (object_var.get())
+ object_var->InstanceDeleted();
+
+ // Clear the object from the var mapping and the live instance object list.
+ live_vars_.erase(*current);
+ data.object_vars.erase(*current);
+ }
+ DCHECK(data.object_vars.empty());
+
+ if (delete_instance)
+ instance_map_.erase(found);
+}
+
uint32 ResourceTracker::GetLiveObjectsForInstance(
PP_Instance instance) const {
InstanceMap::const_iterator found = instance_map_.find(instance);
@@ -228,59 +286,11 @@ PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) {
}
void ResourceTracker::InstanceDeleted(PP_Instance instance) {
- DLOG_IF(ERROR, !CheckIdType(instance, PP_ID_TYPE_INSTANCE))
- << instance << " is not a PP_Instance.";
- InstanceMap::iterator found = instance_map_.find(instance);
- if (found == instance_map_.end()) {
- NOTREACHED();
- return;
- }
- InstanceData& data = found->second;
-
- // Force release all plugin references to resources associated with the
- // deleted instance.
- ResourceSet::iterator cur_res = data.resources.begin();
- while (cur_res != data.resources.end()) {
- ResourceMap::iterator found_resource = live_resources_.find(*cur_res);
- if (found_resource == live_resources_.end()) {
- NOTREACHED();
- } else {
- Resource* resource = found_resource->second.first;
-
- // Must delete from the resource set first since the resource's instance
- // pointer will get zeroed out in LastPluginRefWasDeleted.
- resource->LastPluginRefWasDeleted(true);
- live_resources_.erase(*cur_res);
- }
-
- // Iterators to a set are stable so we can iterate the set while the items
- // are being deleted as long as we're careful not to delete the item we're
- // holding an iterator to.
- ResourceSet::iterator current = cur_res++;
- data.resources.erase(current);
- }
- DCHECK(data.resources.empty());
-
- // Force delete all var references.
- VarSet::iterator cur_var = data.object_vars.begin();
- while (cur_var != data.object_vars.end()) {
- VarSet::iterator current = cur_var++;
-
- // Tell the corresponding ObjectVar that the instance is gone.
- PP_Var object_pp_var;
- object_pp_var.type = PP_VARTYPE_OBJECT;
- object_pp_var.value.as_id = *current;
- scoped_refptr<ObjectVar> object_var(ObjectVar::FromPPVar(object_pp_var));
- if (object_var.get())
- object_var->InstanceDeleted();
-
- // Clear the object from the var mapping and the live instance object list.
- live_vars_.erase(*current);
- data.object_vars.erase(*current);
- }
- DCHECK(data.object_vars.empty());
+ CleanupInstanceData(instance, true);
+}
- instance_map_.erase(found);
+void ResourceTracker::InstanceCrashed(PP_Instance instance) {
+ CleanupInstanceData(instance, false);
}
PluginInstance* ResourceTracker::GetInstance(PP_Instance instance) {
diff --git a/webkit/plugins/ppapi/resource_tracker.h b/webkit/plugins/ppapi/resource_tracker.h
index 1187dda..20f3a2e 100644
--- a/webkit/plugins/ppapi/resource_tracker.h
+++ b/webkit/plugins/ppapi/resource_tracker.h
@@ -87,8 +87,11 @@ class ResourceTracker {
// The given handle should be one generated by AddInstance.
void InstanceDeleted(PP_Instance instance);
+ void InstanceCrashed(PP_Instance instance);
+
// Returns a pointer to the plugin instance object associated with the given
- // instance handle. The return value will be NULL if the handle is invalid.
+ // instance handle. The return value will be NULL if the handle is invalid or
+ // if the instance has crashed.
PluginInstance* GetInstance(PP_Instance instance);
private:
@@ -117,6 +120,11 @@ class ResourceTracker {
// The same as AddResource but for Var, and returns the new Var ID.
int32 AddVar(Var* var);
+ // Force frees all vars and resources associated with the given instance.
+ // If delete_instance is true, the instance tracking information will also
+ // be deleted.
+ void CleanupInstanceData(PP_Instance instance, bool delete_instance);
+
// Overrides the singleton object. This is used for tests which want to
// specify their own tracker (otherwise, you can get cross-talk between
// tests since the data will live into the subsequent tests).