15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
6bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/host_globals.h"
7bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/host_var_tracker.h"
8bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/mock_resource.h"
9bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/npapi_glue.h"
10bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/npobject_var.h"
1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/test/ppapi_unittest.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppp_instance.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/npapi/bindings/npruntime.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebBindings.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::NPObjectVar;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace content {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tracked NPObjects -----------------------------------------------------------
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int g_npobjects_alive = 0;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrackedClassDeallocate(NPObject* npobject) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_npobjects_alive--;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete npobject;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPClass g_tracked_npclass = {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NP_CLASS_STRUCT_VERSION,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &TrackedClassDeallocate,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a new tracked NPObject with a refcount of 1. You'll want to put this
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a NPObjectReleaser to free this ref when the test completes.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPObject* NewTrackedNPObject() {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject* object = new NPObject;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object->_class = &g_tracked_npclass;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object->referenceCount = 1;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_npobjects_alive++;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return object;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReleaseNPObject {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator()(NPObject* o) const {
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    blink::WebBindings::releaseObject(o);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handles automatically releasing a reference to the NPObject on destruction.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It's assumed the input has a ref already taken.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef scoped_ptr_malloc<NPObject, ReleaseNPObject> NPObjectReleaser;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HostVarTrackerTest : public PpapiUnittest {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostVarTrackerTest() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostVarTracker& tracker() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *HostGlobals::Get()->host_var_tracker();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a second instance (the test harness already creates & manages one).
8458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  scoped_refptr<PepperPluginInstanceImpl> instance2(
853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      PepperPluginInstanceImpl::Create(NULL, module(), NULL, GURL()));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Instance pp_instance2 = instance2->pp_instance();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make an object var.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObjectReleaser npobject(NewTrackedNPObject());
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NPObjectToPPVarForTest(instance2.get(), npobject.get());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, g_npobjects_alive);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Free the instance, this should release the ObjectVar.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance2 = NULL;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure that using the same NPObject should give the same PP_Var
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// each time.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(HostVarTrackerTest, ReuseVar) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObjectReleaser npobject(NewTrackedNPObject());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PP_Var pp_object1 = NPObjectToPPVarForTest(instance(), npobject.get());
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PP_Var pp_object2 = NPObjectToPPVarForTest(instance(), npobject.get());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The two results should be the same.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(pp_object1.value.as_id, pp_object2.value.as_id);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The objects should be able to get us back to the associated NPObject.
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // This ObjectVar must be released before we do NPObjectToPPVarForTest again
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // below so it gets freed and we get a new identifier.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<NPObjectVar> check_object(NPObjectVar::FromPPVar(pp_object1));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(check_object.get());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(instance()->pp_instance(), check_object->pp_instance());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(npobject.get(), check_object->np_object());
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove both of the refs we made above.
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ppapi::VarTracker* var_tracker =
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ppapi::PpapiGlobals::Get()->GetVarTracker();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing the resource should free the internal ref, and so making a new
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one now should generate a new ID.
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PP_Var pp_object3 = NPObjectToPPVarForTest(instance(), npobject.get());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(pp_object1.value.as_id, pp_object3.value.as_id);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object3.value.as_id));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace content
135