diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-26 20:56:50 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-26 20:56:50 +0000 |
commit | a26493b62866d90f205d0855b0682c20007cc339 (patch) | |
tree | fe00f64bc489f137b61bd3afa0b16f5f63f4566b /content/plugin | |
parent | b6adb05b1dab052cd49be81e548a56e133edb189 (diff) | |
download | chromium_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.cc | 6 | ||||
-rw-r--r-- | content/plugin/npobject_stub.cc | 6 | ||||
-rw-r--r-- | content/plugin/npobject_util.cc | 34 | ||||
-rw-r--r-- | content/plugin/plugin_channel_base.cc | 31 | ||||
-rw-r--r-- | content/plugin/plugin_channel_base.h | 39 |
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_; |