summaryrefslogtreecommitdiffstats
path: root/content/plugin
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 20:56:50 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 20:56:50 +0000
commita26493b62866d90f205d0855b0682c20007cc339 (patch)
treefe00f64bc489f137b61bd3afa0b16f5f63f4566b /content/plugin
parentb6adb05b1dab052cd49be81e548a56e133edb189 (diff)
downloadchromium_src-a26493b62866d90f205d0855b0682c20007cc339.zip
chromium_src-a26493b62866d90f205d0855b0682c20007cc339.tar.gz
chromium_src-a26493b62866d90f205d0855b0682c20007cc339.tar.bz2
Preserves NPObject identity for objects created in a plugin and passed to JavaScript.
BUG=5751, 22631 TEST=ui_tests w/ the addition of newly added NPObjectIdentityTest. Patch contributed by Kelly Norton (knorton@google.com), original review: http://codereview.chromium.org/7037027/ git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86893 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/plugin')
-rw-r--r--content/plugin/npobject_proxy.cc6
-rw-r--r--content/plugin/npobject_stub.cc6
-rw-r--r--content/plugin/npobject_util.cc34
-rw-r--r--content/plugin/plugin_channel_base.cc31
-rw-r--r--content/plugin/plugin_channel_base.h39
5 files changed, 103 insertions, 13 deletions
diff --git a/content/plugin/npobject_proxy.cc b/content/plugin/npobject_proxy.cc
index 5c08724..4a59b6b 100644
--- a/content/plugin/npobject_proxy.cc
+++ b/content/plugin/npobject_proxy.cc
@@ -69,8 +69,10 @@ NPObjectProxy::NPObjectProxy(
NPObjectProxy::~NPObjectProxy() {
if (channel_.get()) {
Send(new NPObjectMsg_Release(route_id_));
- if (channel_.get())
+ if (channel_.get()) {
channel_->RemoveRoute(route_id_);
+ channel_->RemoveMappingForNPObjectProxy(route_id_);
+ }
}
}
@@ -82,7 +84,7 @@ NPObject* NPObjectProxy::Create(PluginChannelBase* channel,
WebBindings::createObject(0, &npclass_proxy_));
obj->proxy = new NPObjectProxy(
channel, route_id, containing_window, page_url);
-
+ channel->AddMappingForNPObjectProxy(route_id, &obj->object);
return reinterpret_cast<NPObject*>(obj);
}
diff --git a/content/plugin/npobject_stub.cc b/content/plugin/npobject_stub.cc
index e7402a8..7ebd8e6 100644
--- a/content/plugin/npobject_stub.cc
+++ b/content/plugin/npobject_stub.cc
@@ -27,6 +27,7 @@ NPObjectStub::NPObjectStub(
route_id_(route_id),
containing_window_(containing_window),
page_url_(page_url) {
+ channel_->AddMappingForNPObjectStub(route_id, npobject);
channel_->AddRoute(route_id, this, this);
// We retain the object just as PluginHost does if everything was in-process.
@@ -35,8 +36,10 @@ NPObjectStub::NPObjectStub(
NPObjectStub::~NPObjectStub() {
channel_->RemoveRoute(route_id_);
- if (npobject_)
+ if (npobject_) {
+ channel_->RemoveMappingForNPObjectStub(route_id_, npobject_);
WebBindings::releaseObject(npobject_);
+ }
}
bool NPObjectStub::Send(IPC::Message* msg) {
@@ -44,6 +47,7 @@ bool NPObjectStub::Send(IPC::Message* msg) {
}
void NPObjectStub::OnPluginDestroyed() {
+ channel_->RemoveMappingForNPObjectStub(route_id_, npobject_);
// We null out the underlying NPObject pointer since it's not valid anymore (
// ScriptController manually deleted the object). As a result,
// OnMessageReceived won't dispatch any more messages. Since this includes
diff --git a/content/plugin/npobject_util.cc b/content/plugin/npobject_util.cc
index c9a2a68..0afd875 100644
--- a/content/plugin/npobject_util.cc
+++ b/content/plugin/npobject_util.cc
@@ -192,11 +192,17 @@ void CreateNPVariantParam(const NPVariant& variant,
// we were supposed to release the corresponding variant
// (release==true), we should still do that.
param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID;
- int route_id = channel->GenerateRouteID();
- new NPObjectStub(
- variant.value.objectValue, channel, route_id, containing_window,
- page_url);
- param->npobject_routing_id = route_id;
+ int route_id = channel->GetExistingRouteForNPObjectStub(
+ variant.value.objectValue);
+ if (route_id != MSG_ROUTING_NONE) {
+ param->npobject_routing_id = route_id;
+ } else {
+ route_id = channel->GenerateRouteID();
+ new NPObjectStub(
+ variant.value.objectValue, channel, route_id,
+ containing_window, page_url);
+ param->npobject_routing_id = route_id;
+ }
} else {
param->type = NPVARIANT_PARAM_VOID;
}
@@ -216,6 +222,7 @@ bool CreateNPVariant(const NPVariant_Param& param,
NPVariant* result,
gfx::NativeViewId containing_window,
const GURL& page_url) {
+ NPObject* object = NULL;
switch (param.type) {
case NPVARIANT_PARAM_VOID:
result->type = NPVariantType_Void;
@@ -244,11 +251,18 @@ bool CreateNPVariant(const NPVariant_Param& param,
break;
case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID:
result->type = NPVariantType_Object;
- result->value.objectValue =
- NPObjectProxy::Create(channel,
- param.npobject_routing_id,
- containing_window,
- page_url);
+ object = channel->GetExistingNPObjectProxy(param.npobject_routing_id);
+ if (object) {
+ WebBindings::retainObject(object);
+ result->value.objectValue = object;
+ } else {
+ result->value.objectValue =
+ object = NPObjectProxy::Create(channel,
+ param.npobject_routing_id,
+ containing_window,
+ page_url);
+ result->value.objectValue = object;
+ }
break;
case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID: {
NPObjectBase* npobject_base =
diff --git a/content/plugin/plugin_channel_base.cc b/content/plugin/plugin_channel_base.cc
index 3b1aa4c..7db967a 100644
--- a/content/plugin/plugin_channel_base.cc
+++ b/content/plugin/plugin_channel_base.cc
@@ -239,3 +239,34 @@ bool PluginChannelBase::OnControlMessageReceived(const IPC::Message& msg) {
void PluginChannelBase::OnChannelError() {
channel_valid_ = false;
}
+
+NPObject* PluginChannelBase::GetExistingNPObjectProxy(int route_id) {
+ ProxyMap::iterator iter = proxy_map_.find(route_id);
+ return iter != proxy_map_.end() ? iter->second : NULL;
+}
+
+int PluginChannelBase::GetExistingRouteForNPObjectStub(NPObject* npobject) {
+ StubMap::iterator iter = stub_map_.find(npobject);
+ return iter != stub_map_.end() ? iter->second : MSG_ROUTING_NONE;
+}
+
+void PluginChannelBase::AddMappingForNPObjectProxy(int route_id,
+ NPObject* object) {
+ proxy_map_[route_id] = object;
+}
+
+void PluginChannelBase::AddMappingForNPObjectStub(int route_id,
+ NPObject* object) {
+ DCHECK(object != NULL);
+ stub_map_[object] = route_id;
+}
+
+void PluginChannelBase::RemoveMappingForNPObjectStub(int route_id,
+ NPObject* object) {
+ DCHECK(object != NULL);
+ stub_map_.erase(object);
+}
+
+void PluginChannelBase::RemoveMappingForNPObjectProxy(int route_id) {
+ proxy_map_.erase(route_id);
+}
diff --git a/content/plugin/plugin_channel_base.h b/content/plugin/plugin_channel_base.h
index fb69980..6621409 100644
--- a/content/plugin/plugin_channel_base.h
+++ b/content/plugin/plugin_channel_base.h
@@ -22,6 +22,28 @@ namespace base {
class MessageLoopProxy;
}
+#if defined(COMPILER_GCC)
+namespace __gnu_cxx {
+
+template<>
+struct hash<NPObject*> {
+ std::size_t operator()(NPObject* const& ptr) const {
+ return hash<size_t>()(reinterpret_cast<size_t>(ptr));
+ }
+};
+
+} // namespace __gnu_cxx
+#elif defined(COMPILER_MSVC)
+namespace stdext {
+
+template<>
+inline size_t hash_value(NPObject* const& ptr) {
+ return hash_value(reinterpret_cast<size_t>(ptr));
+}
+
+} // namespace stdext
+#endif // COMPILER
+
// Encapsulates an IPC channel between a renderer and a plugin process.
class PluginChannelBase : public IPC::Channel::Listener,
public IPC::Message::Sender,
@@ -38,6 +60,17 @@ class PluginChannelBase : public IPC::Channel::Listener,
NPObjectBase* npobject);
void RemoveRoute(int route_id);
+
+ void AddMappingForNPObjectProxy(int route_id, NPObject* object);
+ void RemoveMappingForNPObjectProxy(int route_id);
+
+ void AddMappingForNPObjectStub(int route_id, NPObject* object);
+ void RemoveMappingForNPObjectStub(int route_id, NPObject* object);
+
+ NPObject* GetExistingNPObjectProxy(int route_id);
+ int GetExistingRouteForNPObjectStub(NPObject* npobject);
+
+
// IPC::Message::Sender implementation:
virtual bool Send(IPC::Message* msg);
@@ -122,6 +155,12 @@ class PluginChannelBase : public IPC::Channel::Listener,
typedef base::hash_map<int, NPObjectBase*> ListenerMap;
ListenerMap npobject_listeners_;
+ typedef base::hash_map<int, NPObject*> ProxyMap;
+ ProxyMap proxy_map_;
+
+ typedef base::hash_map<NPObject*, int> StubMap;
+ StubMap stub_map_;
+
// Used to implement message routing functionality to WebPlugin[Delegate]
// objects
MessageRouter router_;