Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: ppapi/tests/test_instance_deprecated.cc

Issue 9403039: PPAPI: Really force-free NPObjects on Instance destruction. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/tests/test_instance_deprecated.h ('k') | ppapi/tests/testing_instance.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/tests/test_instance_deprecated.h" 5 #include "ppapi/tests/test_instance_deprecated.h"
6 6
7 #include <assert.h>
8
9 #include "ppapi/c/ppb_var.h"
7 #include "ppapi/cpp/module.h" 10 #include "ppapi/cpp/module.h"
8 #include "ppapi/cpp/dev/scriptable_object_deprecated.h" 11 #include "ppapi/cpp/dev/scriptable_object_deprecated.h"
9 #include "ppapi/tests/testing_instance.h" 12 #include "ppapi/tests/testing_instance.h"
10 13
11 namespace { 14 namespace {
12 15
13 static const char kSetValueFunction[] = "SetValue"; 16 static const char kSetValueFunction[] = "SetValue";
14 static const char kSetExceptionFunction[] = "SetException"; 17 static const char kSetExceptionFunction[] = "SetException";
15 static const char kReturnValueFunction[] = "ReturnValue"; 18 static const char kReturnValueFunction[] = "ReturnValue";
16 19
17 // ScriptableObject used by instance. 20 // ScriptableObject used by instance.
18 class InstanceSO : public pp::deprecated::ScriptableObject { 21 class InstanceSO : public pp::deprecated::ScriptableObject {
19 public: 22 public:
20 InstanceSO(TestInstance* i) : test_instance_(i) {} 23 InstanceSO(TestInstance* i);
24 virtual ~InstanceSO();
21 25
22 // pp::deprecated::ScriptableObject overrides. 26 // pp::deprecated::ScriptableObject overrides.
23 bool HasMethod(const pp::Var& name, pp::Var* exception); 27 bool HasMethod(const pp::Var& name, pp::Var* exception);
24 pp::Var Call(const pp::Var& name, 28 pp::Var Call(const pp::Var& name,
25 const std::vector<pp::Var>& args, 29 const std::vector<pp::Var>& args,
26 pp::Var* exception); 30 pp::Var* exception);
27 31
28 private: 32 private:
29 TestInstance* test_instance_; 33 TestInstance* test_instance_;
30 }; 34 };
31 35
36 InstanceSO::InstanceSO(TestInstance* i) : test_instance_(i) {
37 // Set up a post-condition for the test so that we can ensure our destructor
38 // is called. This only works in-process right now. Rather than disable the
39 // whole test, we only do this check when running in-process.
40 // TODO(dmichael): Figure out if we want this to work out-of-process, and if
41 // so, fix it. Note that it might just be failing because the
42 // ReleaseObject and Deallocate messages are asynchronous.
43 if (i->testing_interface() &&
44 i->testing_interface()->IsOutOfProcess() == PP_FALSE) {
45 i->instance()->AddPostCondition(
46 "window.document.getElementById('container').instance_object_destroyed"
47 );
48 }
49 }
50
51 InstanceSO::~InstanceSO() {
52 pp::Var exception;
53 pp::Var ret = test_instance_->instance()->ExecuteScript(
54 "document.getElementById('container').instance_object_destroyed=true;");
55 }
56
32 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) { 57 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) {
33 if (!name.is_string()) 58 if (!name.is_string())
34 return false; 59 return false;
35 return name.AsString() == kSetValueFunction || 60 return name.AsString() == kSetValueFunction ||
36 name.AsString() == kSetExceptionFunction || 61 name.AsString() == kSetExceptionFunction ||
37 name.AsString() == kReturnValueFunction; 62 name.AsString() == kReturnValueFunction;
38 } 63 }
39 64
40 pp::Var InstanceSO::Call(const pp::Var& method_name, 65 pp::Var InstanceSO::Call(const pp::Var& method_name,
41 const std::vector<pp::Var>& args, 66 const std::vector<pp::Var>& args,
(...skipping 30 matching lines...) Expand all
72 97
73 TestInstance::TestInstance(TestingInstance* instance) : TestCase(instance) { 98 TestInstance::TestInstance(TestingInstance* instance) : TestCase(instance) {
74 } 99 }
75 100
76 bool TestInstance::Init() { 101 bool TestInstance::Init() {
77 return true; 102 return true;
78 } 103 }
79 104
80 void TestInstance::RunTests(const std::string& filter) { 105 void TestInstance::RunTests(const std::string& filter) {
81 RUN_TEST(ExecuteScript, filter); 106 RUN_TEST(ExecuteScript, filter);
107 RUN_TEST(RecursiveObjects, filter);
108 RUN_TEST(LeakedObjectDestructors, filter);
109 }
110
111 void TestInstance::LeakReferenceAndIgnore(const pp::Var& leaked) {
112 static const PPB_Var* var_interface = static_cast<const PPB_Var*>(
113 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
114 var_interface->AddRef(leaked.pp_var());
115 IgnoreLeakedVar(leaked.pp_var().value.as_id);
82 } 116 }
83 117
84 pp::deprecated::ScriptableObject* TestInstance::CreateTestObject() { 118 pp::deprecated::ScriptableObject* TestInstance::CreateTestObject() {
85 return new InstanceSO(this); 119 return new InstanceSO(this);
86 } 120 }
87 121
88 std::string TestInstance::TestExecuteScript() { 122 std::string TestInstance::TestExecuteScript() {
89 // Simple call back into the plugin. 123 // Simple call back into the plugin.
90 pp::Var exception; 124 pp::Var exception;
91 pp::Var ret = instance_->ExecuteScript( 125 pp::Var ret = instance_->ExecuteScript(
(...skipping 21 matching lines...) Expand all
113 // not to bother fixing this for now. 147 // not to bother fixing this for now.
114 148
115 // Exception caused by string evaluation should be caught. 149 // Exception caused by string evaluation should be caught.
116 exception = pp::Var(); 150 exception = pp::Var();
117 ret = instance_->ExecuteScript("document.doesntExist()", &exception); 151 ret = instance_->ExecuteScript("document.doesntExist()", &exception);
118 ASSERT_TRUE(ret.is_undefined()); 152 ASSERT_TRUE(ret.is_undefined());
119 ASSERT_TRUE(exception.is_string()); // Don't know exactly what it will say. 153 ASSERT_TRUE(exception.is_string()); // Don't know exactly what it will say.
120 154
121 PASS(); 155 PASS();
122 } 156 }
157
158 // A scriptable object that contains other scriptable objects recursively. This
159 // is used to help verify that our scriptable object clean-up code works
160 // properly.
161 class ObjectWithChildren : public pp::deprecated::ScriptableObject {
162 public:
163 ObjectWithChildren(TestInstance* i, int num_descendents) {
164 if (num_descendents > 0) {
165 child_ = pp::VarPrivate(i->instance(),
166 new ObjectWithChildren(i, num_descendents - 1));
167 }
168 }
169 struct IgnoreLeaks {};
170 ObjectWithChildren(TestInstance* i, int num_descendents, IgnoreLeaks) {
171 if (num_descendents > 0) {
172 child_ = pp::VarPrivate(i->instance(),
173 new ObjectWithChildren(i, num_descendents - 1,
174 IgnoreLeaks()));
175 i->IgnoreLeakedVar(child_.pp_var().value.as_id);
176 }
177 }
178 private:
179 pp::VarPrivate child_;
180 };
181
182 std::string TestInstance::TestRecursiveObjects() {
183 // These should be deleted when we exit scope, so should not leak.
184 pp::VarPrivate not_leaked(instance(), new ObjectWithChildren(this, 50));
185
186 // Leak some, but tell TestCase to ignore the leaks. This test is run and then
187 // reloaded (see ppapi_uitest.cc). If these aren't cleaned up when the first
188 // run is torn down, they will show up as leaks in the second run.
189 // NOTE: The ScriptableObjects are actually leaked, but they should be removed
190 // from the tracker. See below for a test that verifies that the
191 // destructor is not run.
192 pp::VarPrivate leaked(
193 instance(),
194 new ObjectWithChildren(this, 50, ObjectWithChildren::IgnoreLeaks()));
195 // Now leak a reference to the root object. This should force the root and
196 // all its descendents to stay in the tracker.
197 LeakReferenceAndIgnore(leaked);
198
199 PASS();
200 }
201
202 // A scriptable object that should cause a crash if its destructor is run. We
203 // don't run the destructor for objects which the plugin leaks. This is to
204 // prevent them doing dangerous things at cleanup time, such as executing script
205 // or creating new objects.
206 class BadDestructorObject : public pp::deprecated::ScriptableObject {
207 public:
208 BadDestructorObject() {}
209 ~BadDestructorObject() {
210 assert(false);
211 }
212 };
213
214 std::string TestInstance::TestLeakedObjectDestructors() {
215 pp::VarPrivate leaked(instance(), new BadDestructorObject());
216 // Leak a reference so it gets deleted on instance shutdown.
217 LeakReferenceAndIgnore(leaked);
218 PASS();
219 }
220
OLDNEW
« no previous file with comments | « ppapi/tests/test_instance_deprecated.h ('k') | ppapi/tests/testing_instance.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698