summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-21 15:59:50 +0000
committerwez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-21 15:59:50 +0000
commita84bb146e64abd5ac95abeee3606469397da69ff (patch)
treeabce1260f6daf31c9e63e4755d11602256e26ba3
parent12841e5838a6a940ef60d8d96980bdec2c076466 (diff)
downloadchromium_src-a84bb146e64abd5ac95abeee3606469397da69ff.zip
chromium_src-a84bb146e64abd5ac95abeee3606469397da69ff.tar.gz
chromium_src-a84bb146e64abd5ac95abeee3606469397da69ff.tar.bz2
Track NPObject ownership by the originating plugins' NPP identifier. [4/6] (Chrome)
This CL makes Chrome-side changes necessary for tracking of NPObject ownership to out-of-process NPAPI plugin instances. Ownership information is now included whenever an NPObject is marshalled across IPC, to be passed when instantiating NPObjectProxy instances for objects. In the plugin process each NPObject is tracked to its owning plugin instance, and browser-owned objects are tracked to a dummy NPP identifier. This depends upon crrev.com/17220002 and is a prerequisite for crrev.com/17208003. BUG=152006 Review URL: https://chromiumcodereview.appspot.com/17208003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207840 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/child/np_channel_base.cc59
-rw-r--r--content/child/np_channel_base.h25
-rw-r--r--content/child/npobject_proxy.cc5
-rw-r--r--content/child/npobject_proxy.h3
-rw-r--r--content/child/npobject_stub.h2
-rw-r--r--content/child/npobject_util.cc12
-rw-r--r--content/child/plugin_param_traits.cc7
-rw-r--r--content/child/plugin_param_traits.h5
-rw-r--r--content/content_plugin.gypi1
-rw-r--r--content/plugin/plugin_channel.cc11
-rw-r--r--content/plugin/plugin_channel.h4
-rw-r--r--content/plugin/webplugin_delegate_stub.cc15
-rw-r--r--content/plugin/webplugin_proxy.cc14
-rw-r--r--content/renderer/webplugin_delegate_proxy.cc11
-rw-r--r--webkit/plugins/npapi/webplugin_impl.cc18
-rw-r--r--webkit/renderer/cpp_variant_unittest.cc60
16 files changed, 204 insertions, 48 deletions
diff --git a/content/child/np_channel_base.cc b/content/child/np_channel_base.cc
index 81b848b..23805e7 100644
--- a/content/child/np_channel_base.cc
+++ b/content/child/np_channel_base.cc
@@ -72,12 +72,19 @@ NPChannelBase::NPChannelBase()
non_npobject_count_(0),
peer_pid_(0),
in_remove_route_(false),
+ default_owner_(NULL),
channel_valid_(false),
in_unblock_dispatch_(0),
send_unblocking_only_during_unblock_dispatch_(false) {
}
NPChannelBase::~NPChannelBase() {
+ // TODO(wez): Establish why these would ever be non-empty at teardown.
+ //DCHECK(npobject_listeners_.empty());
+ //DCHECK(proxy_map_.empty());
+ //DCHECK(stub_map_.empty());
+ DCHECK(owner_to_route_.empty());
+ DCHECK(route_to_owner_.empty());
}
NPChannelBase* NPChannelBase::GetCurrentChannel() {
@@ -271,21 +278,15 @@ void NPChannelBase::OnChannelError() {
}
}
-NPObject* NPChannelBase::GetExistingNPObjectProxy(int route_id) {
- ProxyMap::iterator iter = proxy_map_.find(route_id);
- return iter != proxy_map_.end() ? iter->second : NULL;
-}
-
-int NPChannelBase::GetExistingRouteForNPObjectStub(NPObject* npobject) {
- StubMap::iterator iter = stub_map_.find(npobject);
- return iter != stub_map_.end() ? iter->second : MSG_ROUTING_NONE;
-}
-
void NPChannelBase::AddMappingForNPObjectProxy(int route_id,
NPObject* object) {
proxy_map_[route_id] = object;
}
+void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) {
+ proxy_map_.erase(route_id);
+}
+
void NPChannelBase::AddMappingForNPObjectStub(int route_id,
NPObject* object) {
DCHECK(object != NULL);
@@ -298,8 +299,42 @@ void NPChannelBase::RemoveMappingForNPObjectStub(int route_id,
stub_map_.erase(object);
}
-void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) {
- proxy_map_.erase(route_id);
+void NPChannelBase::AddMappingForNPObjectOwner(int route_id,
+ struct _NPP* owner) {
+ DCHECK(owner != NULL);
+ route_to_owner_[route_id] = owner;
+ owner_to_route_[owner] = route_id;
+}
+
+void NPChannelBase::SetDefaultNPObjectOwner(struct _NPP* owner) {
+ DCHECK(owner != NULL);
+ default_owner_ = owner;
+}
+
+void NPChannelBase::RemoveMappingForNPObjectOwner(int route_id) {
+ DCHECK(route_to_owner_.find(route_id) != route_to_owner_.end());
+ owner_to_route_.erase(route_to_owner_[route_id]);
+ route_to_owner_.erase(route_id);
+}
+
+NPObject* NPChannelBase::GetExistingNPObjectProxy(int route_id) {
+ ProxyMap::iterator iter = proxy_map_.find(route_id);
+ return iter != proxy_map_.end() ? iter->second : NULL;
+}
+
+int NPChannelBase::GetExistingRouteForNPObjectStub(NPObject* npobject) {
+ StubMap::iterator iter = stub_map_.find(npobject);
+ return iter != stub_map_.end() ? iter->second : MSG_ROUTING_NONE;
+}
+
+NPP NPChannelBase::GetExistingNPObjectOwner(int route_id) {
+ RouteToOwnerMap::iterator iter = route_to_owner_.find(route_id);
+ return iter != route_to_owner_.end() ? iter->second : default_owner_;
+}
+
+int NPChannelBase::GetExistingRouteForNPObjectOwner(NPP owner) {
+ OwnerToRouteMap::iterator iter = owner_to_route_.find(owner);
+ return iter != owner_to_route_.end() ? iter->second : MSG_ROUTING_NONE;
}
} // namespace content
diff --git a/content/child/np_channel_base.h b/content/child/np_channel_base.h
index 06e9991..a89e5bf 100644
--- a/content/child/np_channel_base.h
+++ b/content/child/np_channel_base.h
@@ -31,6 +31,13 @@ struct hash<NPObject*> {
}
};
+template<>
+struct hash<struct _NPP*> {
+ std::size_t operator()(struct _NPP* const& ptr) const {
+ return hash<size_t>()(reinterpret_cast<size_t>(ptr));
+ }
+};
+
} // namespace __gnu_cxx
#elif defined(COMPILER_MSVC)
namespace stdext {
@@ -61,16 +68,20 @@ class NPChannelBase : public IPC::Listener,
void AddRoute(int route_id, IPC::Listener* 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);
+ void AddMappingForNPObjectOwner(int route_id, struct _NPP* owner);
+ void SetDefaultNPObjectOwner(struct _NPP* owner);
+ void RemoveMappingForNPObjectOwner(int route_id);
+
NPObject* GetExistingNPObjectProxy(int route_id);
int GetExistingRouteForNPObjectStub(NPObject* npobject);
-
+ struct _NPP* GetExistingNPObjectOwner(int route_id);
+ int GetExistingRouteForNPObjectOwner(struct _NPP* owner);
// IPC::Sender implementation:
virtual bool Send(IPC::Message* msg) OVERRIDE;
@@ -171,6 +182,16 @@ class NPChannelBase : public IPC::Listener,
typedef base::hash_map<NPObject*, int> StubMap;
StubMap stub_map_;
+ typedef base::hash_map<struct _NPP*, int> OwnerToRouteMap;
+ OwnerToRouteMap owner_to_route_;
+
+ typedef base::hash_map<int, struct _NPP*> RouteToOwnerMap;
+ RouteToOwnerMap route_to_owner_;
+
+ // Used on the plugin side to represent any object received that does
+ // not belong to a plugin instance.
+ struct _NPP* default_owner_;
+
// Used to implement message routing functionality to WebPlugin[Delegate]
// objects
MessageRouter router_;
diff --git a/content/child/npobject_proxy.cc b/content/child/npobject_proxy.cc
index 305ce85..1f732a5 100644
--- a/content/child/npobject_proxy.cc
+++ b/content/child/npobject_proxy.cc
@@ -85,9 +85,10 @@ NPObjectProxy::~NPObjectProxy() {
NPObject* NPObjectProxy::Create(NPChannelBase* channel,
int route_id,
int render_view_id,
- const GURL& page_url) {
+ const GURL& page_url,
+ NPP owner) {
NPObjectWrapper* obj = reinterpret_cast<NPObjectWrapper*>(
- WebBindings::createObject(0, &npclass_proxy_));
+ WebBindings::createObject(owner, &npclass_proxy_));
obj->proxy = new NPObjectProxy(channel, route_id, render_view_id, page_url);
channel->AddMappingForNPObjectProxy(route_id, &obj->object);
return reinterpret_cast<NPObject*>(obj);
diff --git a/content/child/npobject_proxy.h b/content/child/npobject_proxy.h
index ab7815c..ad16210 100644
--- a/content/child/npobject_proxy.h
+++ b/content/child/npobject_proxy.h
@@ -38,7 +38,8 @@ class NPObjectProxy : public IPC::Listener,
static NPObject* Create(NPChannelBase* channel,
int route_id,
int render_view_id,
- const GURL& page_url);
+ const GURL& page_url,
+ NPP owner);
// IPC::Sender implementation:
virtual bool Send(IPC::Message* msg) OVERRIDE;
diff --git a/content/child/npobject_stub.h b/content/child/npobject_stub.h
index 76b19b4..70d3fbd 100644
--- a/content/child/npobject_stub.h
+++ b/content/child/npobject_stub.h
@@ -40,7 +40,7 @@ class NPObjectStub : public IPC::Listener,
virtual ~NPObjectStub();
// Schedules tear-down of this stub. The underlying NPObject reference is
- // released, and further invokations form the IPC channel will fail once this
+ // released, and further invokations from the IPC channel will fail once this
// call has returned. Deletion of the stub is deferred to the main loop, in
// case it is touched as the stack unwinds. DeleteSoon() is safe to call
// more than once, until control returns to the main loop.
diff --git a/content/child/npobject_util.cc b/content/child/npobject_util.cc
index 80fed0e..7b4953c 100644
--- a/content/child/npobject_util.cc
+++ b/content/child/npobject_util.cc
@@ -204,6 +204,11 @@ void CreateNPVariantParam(const NPVariant& variant,
page_url);
param->npobject_routing_id = route_id;
}
+
+ // Include the object's owner.
+ NPP owner = WebBindings::getObjectOwner(variant.value.objectValue);
+ param->npobject_owner_id =
+ channel->GetExistingRouteForNPObjectOwner(owner);
} else {
param->type = NPVARIANT_PARAM_VOID;
}
@@ -259,11 +264,16 @@ bool CreateNPVariant(const NPVariant_Param& param,
WebBindings::retainObject(object);
result->value.objectValue = object;
} else {
+ NPP owner =
+ channel->GetExistingNPObjectOwner(param.npobject_owner_id);
+ // TODO(wez): Once NPObject tracking lands in Blink, check |owner| and
+ // return NPVariantType_Void if it is NULL.
result->value.objectValue =
NPObjectProxy::Create(channel,
param.npobject_routing_id,
render_view_id,
- page_url);
+ page_url,
+ owner);
}
break;
}
diff --git a/content/child/plugin_param_traits.cc b/content/child/plugin_param_traits.cc
index da1b241..f50aecf 100644
--- a/content/child/plugin_param_traits.cc
+++ b/content/child/plugin_param_traits.cc
@@ -24,7 +24,8 @@ NPVariant_Param::NPVariant_Param()
bool_value(false),
int_value(0),
double_value(0),
- npobject_routing_id(-1) {
+ npobject_routing_id(-1),
+ npobject_owner_id(-1) {
}
NPVariant_Param::~NPVariant_Param() {
@@ -53,6 +54,9 @@ void ParamTraits<NPVariant_Param>::Write(Message* m, const param_type& p) {
// process with NPObjectStub in this process or to identify the raw
// npobject pointer to be used in the callee process.
WriteParam(m, p.npobject_routing_id);
+ // This is a routing Id used to identify the plugin instance that owns
+ // the object, for ownership-tracking purposes.
+ WriteParam(m, p.npobject_owner_id);
} else {
DCHECK(p.type == content::NPVARIANT_PARAM_VOID ||
p.type == content::NPVARIANT_PARAM_NULL);
@@ -79,6 +83,7 @@ bool ParamTraits<NPVariant_Param>::Read(const Message* m,
} else if (r->type == content::NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
r->type == content::NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
result = ReadParam(m, iter, &r->npobject_routing_id);
+ result = ReadParam(m, iter, &r->npobject_owner_id);
} else if ((r->type == content::NPVARIANT_PARAM_VOID) ||
(r->type == content::NPVARIANT_PARAM_NULL)) {
result = true;
diff --git a/content/child/plugin_param_traits.h b/content/child/plugin_param_traits.h
index b8495c6..4e45b03 100644
--- a/content/child/plugin_param_traits.h
+++ b/content/child/plugin_param_traits.h
@@ -31,7 +31,9 @@ enum NPVariant_ParamEnum {
NPVARIANT_PARAM_DOUBLE,
NPVARIANT_PARAM_STRING,
// Used when when the NPObject is running in the caller's process, so we
- // create an NPObjectProxy in the other process.
+ // create an NPObjectProxy in the other process. To support object ownership
+ // tracking the routing-Id of the NPObject's owning plugin instance is
+ // passed alongside that of the object itself.
NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID,
// Used when the NPObject we're sending is running in the callee's process
// (i.e. we have an NPObjectProxy for it). In that case we want the callee
@@ -49,6 +51,7 @@ struct NPVariant_Param {
double double_value;
std::string string_value;
int npobject_routing_id;
+ int npobject_owner_id;
};
struct NPIdentifier_Param {
diff --git a/content/content_plugin.gypi b/content/content_plugin.gypi
index 453879a..e00e563 100644
--- a/content/content_plugin.gypi
+++ b/content/content_plugin.gypi
@@ -8,6 +8,7 @@
'dependencies': [
'../skia/skia.gyp:skia',
'../third_party/npapi/npapi.gyp:npapi',
+ '../third_party/WebKit/public/blink.gyp:blink',
'../webkit/plugins/webkit_plugins.gyp:plugins_common',
'../webkit/support/webkit_support.gyp:glue',
'../webkit/support/webkit_support.gyp:plugins',
diff --git a/content/plugin/plugin_channel.cc b/content/plugin/plugin_channel.cc
index 0ba3773..0c4f463 100644
--- a/content/plugin/plugin_channel.cc
+++ b/content/plugin/plugin_channel.cc
@@ -18,6 +18,7 @@
#include "content/plugin/webplugin_delegate_stub.h"
#include "content/plugin/webplugin_proxy.h"
#include "content/public/common/content_switches.h"
+#include "third_party/WebKit/public/web/WebBindings.h"
#include "webkit/plugins/npapi/plugin_instance.h"
#if defined(OS_POSIX)
@@ -25,6 +26,8 @@
#include "ipc/ipc_channel_posix.h"
#endif
+using WebKit::WebBindings;
+
namespace content {
namespace {
@@ -237,11 +240,17 @@ PluginChannel::PluginChannel()
: renderer_id_(-1),
in_send_(0),
incognito_(false),
- filter_(new MessageFilter()) {
+ filter_(new MessageFilter()),
+ npp_(new struct _NPP) {
set_send_unblocking_only_during_unblock_dispatch();
ChildProcess::current()->AddRefProcess();
const CommandLine* command_line = CommandLine::ForCurrentProcess();
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
+
+ // Register |npp_| as the default owner for any object we receive via IPC,
+ // and register it with WebBindings as a valid owner.
+ SetDefaultNPObjectOwner(npp_.get());
+ WebBindings::registerObjectOwner(npp_.get());
}
bool PluginChannel::OnControlMessageReceived(const IPC::Message& msg) {
diff --git a/content/plugin/plugin_channel.h b/content/plugin/plugin_channel.h
index 7860a17..581a3ee 100644
--- a/content/plugin/plugin_channel.h
+++ b/content/plugin/plugin_channel.h
@@ -92,6 +92,10 @@ class PluginChannel : public NPChannelBase {
bool incognito_; // True if the renderer is in incognito mode.
scoped_refptr<MessageFilter> filter_; // Handles the modal dialog events.
+ // Dummy NPP value used in the plugin process to represent entities other
+ // that other plugin instances for the purpose of object ownership tracking.
+ scoped_ptr<struct _NPP> npp_;
+
DISALLOW_COPY_AND_ASSIGN(PluginChannel);
};
diff --git a/content/plugin/webplugin_delegate_stub.cc b/content/plugin/webplugin_delegate_stub.cc
index afc5022..9b7dd6f 100644
--- a/content/plugin/webplugin_delegate_stub.cc
+++ b/content/plugin/webplugin_delegate_stub.cc
@@ -40,6 +40,10 @@ static void DestroyWebPluginAndDelegate(
// after calling NPP_Destroy on the instance, so delete the stub now.
if (scriptable_object.get())
scriptable_object->DeleteSoon();
+
+ // Un-register the plugin instance as an object owner.
+ WebBindings::unregisterObjectOwner(delegate->GetPluginNPP());
+
// WebPlugin must outlive WebPluginDelegate.
if (delegate)
delegate->PluginDestroyed();
@@ -76,6 +80,9 @@ WebPluginDelegateStub::~WebPluginDelegateStub() {
DestroyWebPluginAndDelegate(
plugin_scriptable_object_, delegate_, webplugin_);
}
+
+ // Remove the NPObject owner mapping for this instance.
+ channel_->RemoveMappingForNPObjectOwner(instance_id_);
}
bool WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) {
@@ -175,6 +182,14 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params,
std::vector<std::string> arg_names = params.arg_names;
std::vector<std::string> arg_values = params.arg_values;
+ // Register the plugin as a valid object owner.
+ WebBindings::registerObjectOwner(delegate_->GetPluginNPP());
+
+ // Add an NPObject owner mapping for this instance, to support ownership
+ // tracking in the renderer.
+ channel_->AddMappingForNPObjectOwner(instance_id_,
+ delegate_->GetPluginNPP());
+
*result = delegate_->Initialize(params.url,
arg_names,
arg_values,
diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc
index 65a8505..8afbfb0 100644
--- a/content/plugin/webplugin_proxy.cc
+++ b/content/plugin/webplugin_proxy.cc
@@ -220,10 +220,15 @@ NPObject* WebPluginProxy::GetWindowScriptNPObject() {
if (!success)
return NULL;
+ // PluginChannel creates a dummy owner identifier for unknown owners, so
+ // use that.
+ NPP owner = channel_->GetExistingNPObjectOwner(MSG_ROUTING_NONE);
+
window_npobject_ = NPObjectProxy::Create(channel_.get(),
npobject_route_id,
host_render_view_routing_id_,
- page_url_);
+ page_url_,
+ owner);
return window_npobject_;
}
@@ -239,10 +244,15 @@ NPObject* WebPluginProxy::GetPluginElement() {
if (!success)
return NULL;
+ // PluginChannel creates a dummy owner identifier for unknown owners, so
+ // use that.
+ NPP owner = channel_->GetExistingNPObjectOwner(MSG_ROUTING_NONE);
+
plugin_element_ = NPObjectProxy::Create(channel_.get(),
npobject_route_id,
host_render_view_routing_id_,
- page_url_);
+ page_url_,
+ owner);
return plugin_element_;
}
diff --git a/content/renderer/webplugin_delegate_proxy.cc b/content/renderer/webplugin_delegate_proxy.cc
index bcf1740..1176743 100644
--- a/content/renderer/webplugin_delegate_proxy.cc
+++ b/content/renderer/webplugin_delegate_proxy.cc
@@ -258,6 +258,10 @@ void WebPluginDelegateProxy::PluginDestroyed() {
// channel went away if this was the last instance.
channel_host_->RemoveRoute(instance_id_);
+ // Remove the mapping between our instance-Id and NPP identifiers, used by
+ // the channel to track object ownership, before releasing it.
+ channel_host_->RemoveMappingForNPObjectOwner(instance_id_);
+
// Release the channel host now. If we are is the last reference to the
// channel, this avoids a race where this renderer asks a new connection to
// the same plugin between now and the time 'this' is actually deleted.
@@ -275,6 +279,7 @@ void WebPluginDelegateProxy::PluginDestroyed() {
// been destroyed by WebKit, at which point WebKit will forcibly deallocate
// the window script object. The window script object stub is unique to the
// plugin instance, so this won't affect other instances.
+ // TODO(wez): Remove this hack.
window_script_object_->DeleteSoon();
}
@@ -363,6 +368,10 @@ bool WebPluginDelegateProxy::Initialize(
channel_host_->AddRoute(instance_id_, this, NULL);
+ // Inform the channel of the mapping between our instance-Id and dummy NPP
+ // identifier, for use in object ownership tracking.
+ channel_host_->AddMappingForNPObjectOwner(instance_id_, GetPluginNPP());
+
// Now tell the PluginInstance in the plugin process to initialize.
PluginMsg_Init_Params params;
params.url = url;
@@ -739,7 +748,7 @@ NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
return NULL;
npobject_ = NPObjectProxy::Create(
- channel_host_.get(), route_id, 0, page_url_);
+ channel_host_.get(), route_id, 0, page_url_, GetPluginNPP());
return WebBindings::retainObject(npobject_);
}
diff --git a/webkit/plugins/npapi/webplugin_impl.cc b/webkit/plugins/npapi/webplugin_impl.cc
index e110309..3754b25 100644
--- a/webkit/plugins/npapi/webplugin_impl.cc
+++ b/webkit/plugins/npapi/webplugin_impl.cc
@@ -260,12 +260,17 @@ bool WebPluginImpl::initialize(WebPluginContainer* container) {
WebKit::WebPlugin* replacement_plugin =
page_delegate_->CreatePluginReplacement(file_path_);
- if (!replacement_plugin || !replacement_plugin->initialize(container))
+ if (!replacement_plugin)
return false;
- container->setPlugin(replacement_plugin);
+ // Disable scripting by this plugin before replacing it with the new
+ // one. This plugin also needs destroying, so use destroy(), which will
+ // implicitly disable scripting while un-setting the container.
destroy();
- return true;
+
+ // Inform the container of the replacement plugin, then initialize it.
+ container->setPlugin(replacement_plugin);
+ return replacement_plugin->initialize(container);
}
delegate_ = plugin_delegate;
@@ -1320,10 +1325,17 @@ bool WebPluginImpl::ReinitializePluginForResponse(
WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate(
file_path_, mime_type_);
+ // Store the plugin's unique identifier, used by the container to track its
+ // script objects, and enable script objects (since Initialize may use them
+ // even if it fails).
+ npp_ = plugin_delegate->GetPluginNPP();
+ container_->allowScriptObjects();
+
bool ok = plugin_delegate && plugin_delegate->Initialize(
plugin_url_, arg_names_, arg_values_, this, load_manually_);
if (!ok) {
+ container_->clearScriptObjects();
container_ = NULL;
// TODO(iyengar) Should we delete the current plugin instance here?
return false;
diff --git a/webkit/renderer/cpp_variant_unittest.cc b/webkit/renderer/cpp_variant_unittest.cc
index 820f64a..1f2d3fe 100644
--- a/webkit/renderer/cpp_variant_unittest.cc
+++ b/webkit/renderer/cpp_variant_unittest.cc
@@ -5,6 +5,7 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebBindings.h"
@@ -76,25 +77,44 @@ static NPClass void_class = { NP_CLASS_STRUCT_VERSION,
MockNPDeallocate,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
-NPObject* MakeVoidObject() {
- g_allocate_call_count = 0;
- g_deallocate_call_count = 0;
- return WebBindings::createObject(NULL, &void_class);
-}
+class CppVariantTest : public testing::Test {
+public:
+ CppVariantTest() : npp_(new struct _NPP) {}
+ virtual ~CppVariantTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ WebBindings::registerObjectOwner(npp_.get());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ WebBindings::unregisterObjectOwner(npp_.get());
+ }
+
+ struct _NPP* npp() { return npp_.get(); }
+
+ NPObject* MakeVoidObject() {
+ g_allocate_call_count = 0;
+ g_deallocate_call_count = 0;
+ return WebBindings::createObject(npp_.get(), &void_class);
+ }
+
+private:
+ scoped_ptr<struct _NPP> npp_;
+};
-TEST(CppVariantTest, NewVariantHasNullType) {
+TEST_F(CppVariantTest, NewVariantHasNullType) {
CppVariant value;
EXPECT_EQ(NPVariantType_Null, value.type);
}
-TEST(CppVariantTest, SetNullSetsType) {
+TEST_F(CppVariantTest, SetNullSetsType) {
CppVariant value;
value.Set(17);
value.SetNull();
EXPECT_EQ(NPVariantType_Null, value.type);
}
-TEST(CppVariantTest, CopyConstructorDoesDeepCopy) {
+TEST_F(CppVariantTest, CopyConstructorDoesDeepCopy) {
CppVariant source;
source.Set("test string");
CppVariant dest = source;
@@ -108,7 +128,7 @@ TEST(CppVariantTest, CopyConstructorDoesDeepCopy) {
CheckString(source, dest);
}
-TEST(CppVariantTest, CopyConstructorIncrementsRefCount) {
+TEST_F(CppVariantTest, CopyConstructorIncrementsRefCount) {
CppVariant source;
NPObject *object = MakeVoidObject();
source.Set(object);
@@ -123,7 +143,7 @@ TEST(CppVariantTest, CopyConstructorIncrementsRefCount) {
CheckObject(dest);
}
-TEST(CppVariantTest, AssignmentDoesDeepCopy) {
+TEST_F(CppVariantTest, AssignmentDoesDeepCopy) {
CppVariant source;
source.Set("test string");
CppVariant dest;
@@ -138,7 +158,7 @@ TEST(CppVariantTest, AssignmentDoesDeepCopy) {
CheckString(source, dest);
}
-TEST(CppVariantTest, AssignmentIncrementsRefCount) {
+TEST_F(CppVariantTest, AssignmentIncrementsRefCount) {
CppVariant source;
NPObject *object = MakeVoidObject();
source.Set(object);
@@ -155,7 +175,7 @@ TEST(CppVariantTest, AssignmentIncrementsRefCount) {
CheckObject(dest);
}
-TEST(CppVariantTest, DestroyingCopyDoesNotCorruptSource) {
+TEST_F(CppVariantTest, DestroyingCopyDoesNotCorruptSource) {
CppVariant source;
source.Set("test string");
std::string before;
@@ -174,7 +194,7 @@ TEST(CppVariantTest, DestroyingCopyDoesNotCorruptSource) {
CheckObject(source);
}
-TEST(CppVariantTest, CopiesTypeAndValueToNPVariant) {
+TEST_F(CppVariantTest, CopiesTypeAndValueToNPVariant) {
NPVariant np;
CppVariant cpp;
@@ -215,7 +235,7 @@ TEST(CppVariantTest, CopiesTypeAndValueToNPVariant) {
WebBindings::releaseVariantValue(&np);
}
-TEST(CppVariantTest, SetsTypeAndValueFromNPVariant) {
+TEST_F(CppVariantTest, SetsTypeAndValueFromNPVariant) {
NPVariant np;
CppVariant cpp;
@@ -273,7 +293,7 @@ TEST(CppVariantTest, SetsTypeAndValueFromNPVariant) {
CheckObject(cpp);
}
-TEST(CppVariantTest, SetsSimpleTypesAndValues) {
+TEST_F(CppVariantTest, SetsSimpleTypesAndValues) {
CppVariant cpp;
cpp.Set(true);
EXPECT_EQ(NPVariantType_Bool, cpp.type);
@@ -319,7 +339,7 @@ TEST(CppVariantTest, SetsSimpleTypesAndValues) {
CheckObject(cpp);
}
-TEST(CppVariantTest, FreeDataSetsToVoid) {
+TEST_F(CppVariantTest, FreeDataSetsToVoid) {
CppVariant cpp;
EXPECT_EQ(NPVariantType_Null, cpp.type);
cpp.Set(12);
@@ -328,7 +348,7 @@ TEST(CppVariantTest, FreeDataSetsToVoid) {
EXPECT_EQ(NPVariantType_Void, cpp.type);
}
-TEST(CppVariantTest, FreeDataReleasesObject) {
+TEST_F(CppVariantTest, FreeDataReleasesObject) {
CppVariant cpp;
NPObject* object = MakeVoidObject();
cpp.Set(object);
@@ -344,7 +364,7 @@ TEST(CppVariantTest, FreeDataReleasesObject) {
EXPECT_EQ(1, g_deallocate_call_count);
}
-TEST(CppVariantTest, IsTypeFunctionsWork) {
+TEST_F(CppVariantTest, IsTypeFunctionsWork) {
CppVariant cpp;
// These should not happen in practice, since voids are not supported
// This test must be first since it just clobbers internal data without
@@ -454,7 +474,7 @@ bool MockNPGetPropertyFunction(NPObject *npobj, NPIdentifier name,
return true;
}
-TEST(CppVariantTest, ToVector) {
+TEST_F(CppVariantTest, ToVector) {
NPClass array_like_class = {
NP_CLASS_STRUCT_VERSION,
0, // NPAllocateFunctionPtr allocate;
@@ -471,7 +491,7 @@ TEST(CppVariantTest, ToVector) {
0 // NPConstructFunctionPtr construct;
};
- NPObject* obj = WebBindings::createObject(NULL, &array_like_class);
+ NPObject* obj = WebBindings::createObject(npp(), &array_like_class);
CppVariant cpp;
cpp.Set(obj);