summaryrefslogtreecommitdiffstats
path: root/webkit/plugins/ppapi/host_var_tracker_unittest.cc
blob: fce822bc1a3817f2427e1ca288d21907cf33c16e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/plugins/ppapi/ppapi_unittest.h"

#include "base/memory/scoped_ptr.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppp_instance.h"
#include "third_party/npapi/bindings/npruntime.h"
#include "third_party/WebKit/public/web/WebBindings.h"
#include "webkit/plugins/ppapi/host_globals.h"
#include "webkit/plugins/ppapi/host_var_tracker.h"
#include "webkit/plugins/ppapi/mock_plugin_delegate.h"
#include "webkit/plugins/ppapi/mock_resource.h"
#include "webkit/plugins/ppapi/npapi_glue.h"
#include "webkit/plugins/ppapi/npobject_var.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"

using ppapi::NPObjectVar;

namespace webkit {
namespace ppapi {

namespace {

// Tracked NPObjects -----------------------------------------------------------

int g_npobjects_alive = 0;

void TrackedClassDeallocate(NPObject* npobject) {
  g_npobjects_alive--;
  delete npobject;
}

NPClass g_tracked_npclass = {
  NP_CLASS_STRUCT_VERSION,
  NULL,
  &TrackedClassDeallocate,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
};

// Returns a new tracked NPObject with a refcount of 1. You'll want to put this
// in a NPObjectReleaser to free this ref when the test completes.
NPObject* NewTrackedNPObject() {
  NPObject* object = new NPObject;
  object->_class = &g_tracked_npclass;
  object->referenceCount = 1;

  g_npobjects_alive++;
  return object;
}

class ReleaseNPObject {
 public:
  void operator()(NPObject* o) const {
    WebKit::WebBindings::releaseObject(o);
  }
};

// Handles automatically releasing a reference to the NPObject on destruction.
// It's assumed the input has a ref already taken.
typedef scoped_ptr_malloc<NPObject, ReleaseNPObject> NPObjectReleaser;

}  // namespace

class HostVarTrackerTest : public PpapiUnittest {
 public:
  HostVarTrackerTest() {
  }

  HostVarTracker& tracker() {
    return *HostGlobals::Get()->host_var_tracker();
  }
};

TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) {
  // Make a second instance (the test harness already creates & manages one).
  scoped_refptr<PluginInstance> instance2(
      PluginInstance::Create(delegate(), NULL, module(), NULL, GURL()));
  PP_Instance pp_instance2 = instance2->pp_instance();

  // Make an object var.
  NPObjectReleaser npobject(NewTrackedNPObject());
  NPObjectToPPVarForTest(instance2.get(), npobject.get());

  EXPECT_EQ(1, g_npobjects_alive);
  EXPECT_EQ(1, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));

  // Free the instance, this should release the ObjectVar.
  instance2 = NULL;
  EXPECT_EQ(0, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
}

// Make sure that using the same NPObject should give the same PP_Var
// each time.
TEST_F(HostVarTrackerTest, ReuseVar) {
  NPObjectReleaser npobject(NewTrackedNPObject());

  PP_Var pp_object1 = NPObjectToPPVarForTest(instance(), npobject.get());
  PP_Var pp_object2 = NPObjectToPPVarForTest(instance(), npobject.get());

  // The two results should be the same.
  EXPECT_EQ(pp_object1.value.as_id, pp_object2.value.as_id);

  // The objects should be able to get us back to the associated NPObject.
  // This ObjectVar must be released before we do NPObjectToPPVarForTest again
  // below so it gets freed and we get a new identifier.
  {
    scoped_refptr<NPObjectVar> check_object(NPObjectVar::FromPPVar(pp_object1));
    ASSERT_TRUE(check_object.get());
    EXPECT_EQ(instance()->pp_instance(), check_object->pp_instance());
    EXPECT_EQ(npobject.get(), check_object->np_object());
  }

  // Remove both of the refs we made above.
  ::ppapi::VarTracker* var_tracker =
      ::ppapi::PpapiGlobals::Get()->GetVarTracker();
  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id));
  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id));

  // Releasing the resource should free the internal ref, and so making a new
  // one now should generate a new ID.
  PP_Var pp_object3 = NPObjectToPPVarForTest(instance(), npobject.get());
  EXPECT_NE(pp_object1.value.as_id, pp_object3.value.as_id);
  var_tracker->ReleaseVar(static_cast<int32_t>(pp_object3.value.as_id));
}

}  // namespace ppapi
}  // namespace webkit