host_var_tracker_unittest.cc revision 58e6fbe4ee35d65e14b626c557d37565bf8ad179
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/renderer/pepper/ppapi_unittest.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "content/renderer/pepper/host_globals.h"
9#include "content/renderer/pepper/host_var_tracker.h"
10#include "content/renderer/pepper/mock_plugin_delegate.h"
11#include "content/renderer/pepper/mock_resource.h"
12#include "content/renderer/pepper/npapi_glue.h"
13#include "content/renderer/pepper/npobject_var.h"
14#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
15#include "ppapi/c/pp_var.h"
16#include "ppapi/c/ppp_instance.h"
17#include "third_party/npapi/bindings/npruntime.h"
18#include "third_party/WebKit/public/web/WebBindings.h"
19
20using ppapi::NPObjectVar;
21
22namespace content {
23
24namespace {
25
26// Tracked NPObjects -----------------------------------------------------------
27
28int g_npobjects_alive = 0;
29
30void TrackedClassDeallocate(NPObject* npobject) {
31  g_npobjects_alive--;
32  delete npobject;
33}
34
35NPClass g_tracked_npclass = {
36  NP_CLASS_STRUCT_VERSION,
37  NULL,
38  &TrackedClassDeallocate,
39  NULL,
40  NULL,
41  NULL,
42  NULL,
43  NULL,
44  NULL,
45  NULL,
46  NULL,
47  NULL,
48};
49
50// Returns a new tracked NPObject with a refcount of 1. You'll want to put this
51// in a NPObjectReleaser to free this ref when the test completes.
52NPObject* NewTrackedNPObject() {
53  NPObject* object = new NPObject;
54  object->_class = &g_tracked_npclass;
55  object->referenceCount = 1;
56
57  g_npobjects_alive++;
58  return object;
59}
60
61class ReleaseNPObject {
62 public:
63  void operator()(NPObject* o) const {
64    WebKit::WebBindings::releaseObject(o);
65  }
66};
67
68// Handles automatically releasing a reference to the NPObject on destruction.
69// It's assumed the input has a ref already taken.
70typedef scoped_ptr_malloc<NPObject, ReleaseNPObject> NPObjectReleaser;
71
72}  // namespace
73
74class HostVarTrackerTest : public PpapiUnittest {
75 public:
76  HostVarTrackerTest() {
77  }
78
79  HostVarTracker& tracker() {
80    return *HostGlobals::Get()->host_var_tracker();
81  }
82};
83
84TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) {
85  // Make a second instance (the test harness already creates & manages one).
86  scoped_refptr<PepperPluginInstanceImpl> instance2(
87      PepperPluginInstanceImpl::Create(
88          delegate(), NULL, module(), NULL, GURL()));
89  PP_Instance pp_instance2 = instance2->pp_instance();
90
91  // Make an object var.
92  NPObjectReleaser npobject(NewTrackedNPObject());
93  NPObjectToPPVarForTest(instance2.get(), npobject.get());
94
95  EXPECT_EQ(1, g_npobjects_alive);
96  EXPECT_EQ(1, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
97
98  // Free the instance, this should release the ObjectVar.
99  instance2 = NULL;
100  EXPECT_EQ(0, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
101}
102
103// Make sure that using the same NPObject should give the same PP_Var
104// each time.
105TEST_F(HostVarTrackerTest, ReuseVar) {
106  NPObjectReleaser npobject(NewTrackedNPObject());
107
108  PP_Var pp_object1 = NPObjectToPPVarForTest(instance(), npobject.get());
109  PP_Var pp_object2 = NPObjectToPPVarForTest(instance(), npobject.get());
110
111  // The two results should be the same.
112  EXPECT_EQ(pp_object1.value.as_id, pp_object2.value.as_id);
113
114  // The objects should be able to get us back to the associated NPObject.
115  // This ObjectVar must be released before we do NPObjectToPPVarForTest again
116  // below so it gets freed and we get a new identifier.
117  {
118    scoped_refptr<NPObjectVar> check_object(NPObjectVar::FromPPVar(pp_object1));
119    ASSERT_TRUE(check_object.get());
120    EXPECT_EQ(instance()->pp_instance(), check_object->pp_instance());
121    EXPECT_EQ(npobject.get(), check_object->np_object());
122  }
123
124  // Remove both of the refs we made above.
125  ::ppapi::VarTracker* var_tracker =
126      ::ppapi::PpapiGlobals::Get()->GetVarTracker();
127  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id));
128  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id));
129
130  // Releasing the resource should free the internal ref, and so making a new
131  // one now should generate a new ID.
132  PP_Var pp_object3 = NPObjectToPPVarForTest(instance(), npobject.get());
133  EXPECT_NE(pp_object1.value.as_id, pp_object3.value.as_id);
134  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object3.value.as_id));
135}
136
137}  // namespace content
138