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

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

Issue 472693002: Minor changes to allow Pepper InstancePrivate tests to pass with gin (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 3 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') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 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 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> 7 #include <assert.h>
8 8
9 #include "ppapi/c/ppb_var.h" 9 #include "ppapi/c/ppb_var.h"
10 #include "ppapi/cpp/module.h" 10 #include "ppapi/cpp/module.h"
11 #include "ppapi/cpp/dev/scriptable_object_deprecated.h"
12 #include "ppapi/tests/testing_instance.h" 11 #include "ppapi/tests/testing_instance.h"
13 12
14 namespace {
15
16 static const char kSetValueFunction[] = "SetValue"; 13 static const char kSetValueFunction[] = "SetValue";
17 static const char kSetExceptionFunction[] = "SetException"; 14 static const char kSetExceptionFunction[] = "SetException";
18 static const char kReturnValueFunction[] = "ReturnValue"; 15 static const char kReturnValueFunction[] = "ReturnValue";
19 16
20 // ScriptableObject used by instance.
21 class InstanceSO : public pp::deprecated::ScriptableObject {
22 public:
23 explicit InstanceSO(TestInstance* i);
24 virtual ~InstanceSO();
25
26 // pp::deprecated::ScriptableObject overrides.
27 bool HasMethod(const pp::Var& name, pp::Var* exception);
28 pp::Var Call(const pp::Var& name,
29 const std::vector<pp::Var>& args,
30 pp::Var* exception);
31
32 private:
33 TestInstance* test_instance_;
34 // For out-of-process, the InstanceSO might be deleted after the instance was
35 // already destroyed, so we can't rely on test_instance_->testing_interface()
36 // being valid. Therefore we store our own.
37 const PPB_Testing_Private* testing_interface_;
38 };
39
40 InstanceSO::InstanceSO(TestInstance* i) 17 InstanceSO::InstanceSO(TestInstance* i)
41 : test_instance_(i), 18 : test_instance_(i),
42 testing_interface_(i->testing_interface()) { 19 testing_interface_(i->testing_interface()) {
43 // Set up a post-condition for the test so that we can ensure our destructor
44 // is called. This only works reliably in-process. Out-of-process, it only
45 // can work when the renderer stays alive a short while after the plugin
46 // instance is destroyed. If the renderer is being shut down, too much happens
47 // asynchronously for the out-of-process case to work reliably. In
48 // particular:
49 // - The Var ReleaseObject message is asynchronous.
50 // - The PPB_Var_Deprecated host-side proxy posts a task to actually release
51 // the object when the ReleaseObject message is received.
52 // - The PPP_Class Deallocate message is asynchronous.
53 // At time of writing this comment, if you modify the code so that the above
54 // happens synchronously, and you remove the restriction that the plugin can't
55 // be unblocked by a sync message, then this check actually passes reliably
56 // for out-of-process. But we don't want to make any of those changes, so we
57 // just skip the check.
58 if (testing_interface_->IsOutOfProcess() == PP_FALSE) {
59 i->instance()->AddPostCondition(
60 "window.document.getElementById('container').instance_object_destroyed"
61 );
62 }
63 } 20 }
64 21
65 InstanceSO::~InstanceSO() { 22 InstanceSO::~InstanceSO() {
66 if (testing_interface_->IsOutOfProcess() == PP_FALSE) { 23 if (test_instance_)
67 // TODO(dmichael): It would probably be best to make in-process consistent 24 test_instance_->clear_instance_so();
68 // with out-of-process. That would mean that the instance
69 // would already be destroyed at this point.
70 pp::Var ret = test_instance_->instance()->ExecuteScript(
71 "document.getElementById('container').instance_object_destroyed=true;");
72 } else {
73 // Out-of-process, this destructor might not actually get invoked. See the
74 // comment in InstanceSO's constructor for an explanation. Also, instance()
75 // has already been destroyed :-(. So we can't really do anything here.
76 }
77 } 25 }
78 26
79 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) { 27 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) {
80 if (!name.is_string()) 28 if (!name.is_string())
81 return false; 29 return false;
82 return name.AsString() == kSetValueFunction || 30 return name.AsString() == kSetValueFunction ||
83 name.AsString() == kSetExceptionFunction || 31 name.AsString() == kSetExceptionFunction ||
84 name.AsString() == kReturnValueFunction; 32 name.AsString() == kReturnValueFunction;
85 } 33 }
86 34
87 pp::Var InstanceSO::Call(const pp::Var& method_name, 35 pp::Var InstanceSO::Call(const pp::Var& method_name,
88 const std::vector<pp::Var>& args, 36 const std::vector<pp::Var>& args,
89 pp::Var* exception) { 37 pp::Var* exception) {
90 if (!method_name.is_string()) 38 if (!method_name.is_string())
91 return false; 39 return false;
92 std::string name = method_name.AsString(); 40 std::string name = method_name.AsString();
93 41
94 if (name == kSetValueFunction) { 42 if (name == kSetValueFunction) {
95 if (args.size() != 1 || !args[0].is_string()) 43 if (args.size() != 1 || !args[0].is_string())
96 *exception = pp::Var("Bad argument to SetValue(<string>)"); 44 *exception = pp::Var("Bad argument to SetValue(<string>)");
97 else 45 else if (test_instance_)
98 test_instance_->set_string(args[0].AsString()); 46 test_instance_->set_string(args[0].AsString());
99 } else if (name == kSetExceptionFunction) { 47 } else if (name == kSetExceptionFunction) {
100 if (args.size() != 1 || !args[0].is_string()) 48 if (args.size() != 1 || !args[0].is_string())
101 *exception = pp::Var("Bad argument to SetException(<string>)"); 49 *exception = pp::Var("Bad argument to SetException(<string>)");
102 else 50 else
103 *exception = args[0]; 51 *exception = args[0];
104 } else if (name == kReturnValueFunction) { 52 } else if (name == kReturnValueFunction) {
105 if (args.size() != 1) 53 if (args.size() != 1)
106 *exception = pp::Var("Need single arg to call ReturnValue"); 54 *exception = pp::Var("Need single arg to call ReturnValue");
107 else 55 else
108 return args[0]; 56 return args[0];
109 } else { 57 } else {
110 *exception = pp::Var("Bad function call"); 58 *exception = pp::Var("Bad function call");
111 } 59 }
112 60
113 return pp::Var(); 61 return pp::Var();
114 } 62 }
115 63
116 } // namespace
117
118 REGISTER_TEST_CASE(Instance); 64 REGISTER_TEST_CASE(Instance);
119 65
120 TestInstance::TestInstance(TestingInstance* instance) : TestCase(instance) { 66 TestInstance::TestInstance(TestingInstance* instance)
121 } 67 : TestCase(instance),
68 instance_so_(NULL) {}
122 69
123 bool TestInstance::Init() { 70 bool TestInstance::Init() {
124 return true; 71 return true;
125 } 72 }
126 73
127 TestInstance::~TestInstance() { 74 TestInstance::~TestInstance() {
128 ResetTestObject(); 75 ResetTestObject();
129 // When running tests in process, some post conditions check that teardown 76 if (testing_interface_->IsOutOfProcess() == PP_FALSE) {
130 // happened successfully. We need to run the garbage collector to ensure that 77 // This should cause the instance object's descructor to be called.
131 // vars get released.
132 if (testing_interface_->IsOutOfProcess() == PP_FALSE)
133 testing_interface_->RunV8GC(instance_->pp_instance()); 78 testing_interface_->RunV8GC(instance_->pp_instance());
79
80 // Test a post-condition which ensures the instance objects destructor is
81 // called. This only works reliably in-process. Out-of-process, it only
82 // can work when the renderer stays alive a short while after the plugin
83 // instance is destroyed. If the renderer is being shut down, too much
84 // happens asynchronously for the out-of-process case to work reliably. In
85 // particular:
86 // - The Var ReleaseObject message is asynchronous.
87 // - The PPB_Var_Deprecated host-side proxy posts a task to actually
88 // release the object when the ReleaseObject message is received.
89 // - The PPP_Class Deallocate message is asynchronous.
90 // At time of writing this comment, if you modify the code so that the above
91 // happens synchronously, and you remove the restriction that the plugin
92 // can't be unblocked by a sync message, then this check actually passes
93 // reliably for out-of-process. But we don't want to make any of those
94 // changes so we just skip the check.
95 PP_DCHECK(!instance_so_);
96 } else {
97 // Out-of-process, this destructor might not actually get invoked. Clear
98 // the InstanceSOs reference to the instance so there is no UAF.
99 if (instance_so_)
100 instance_so_->clear_test_instance();
101 }
102
134 // Save the fact that we were destroyed in sessionStorage. This tests that 103 // Save the fact that we were destroyed in sessionStorage. This tests that
135 // we can ExecuteScript at instance destruction without crashing. It also 104 // we can ExecuteScript at instance destruction without crashing. It also
136 // allows us to check that ExecuteScript will run and succeed in certain 105 // allows us to check that ExecuteScript will run and succeed in certain
137 // cases. In particular, when the instance is destroyed by normal DOM 106 // cases. In particular, when the instance is destroyed by normal DOM
138 // deletion, ExecuteScript will actually work. See 107 // deletion, ExecuteScript will actually work. See
139 // TestExecuteScriptInInstanceShutdown for that test. Note, however, that 108 // TestExecuteScriptInInstanceShutdown for that test. Note, however, that
140 // ExecuteScript will *not* have an effect when the instance is destroyed 109 // ExecuteScript will *not* have an effect when the instance is destroyed
141 // because the renderer was shut down. 110 // because the renderer was shut down.
142 pp::Var ret = instance()->ExecuteScript( 111 pp::Var ret = instance()->ExecuteScript(
143 "sessionStorage.setItem('instance_destroyed', 'true');"); 112 "sessionStorage.setItem('instance_destroyed', 'true');");
144 } 113 }
145 114
146 void TestInstance::RunTests(const std::string& filter) { 115 void TestInstance::RunTests(const std::string& filter) {
147 RUN_TEST(ExecuteScript, filter); 116 RUN_TEST(ExecuteScript, filter);
148 RUN_TEST(RecursiveObjects, filter); 117 RUN_TEST(RecursiveObjects, filter);
149 RUN_TEST(LeakedObjectDestructors, filter); 118 RUN_TEST(LeakedObjectDestructors, filter);
150 RUN_TEST(SetupExecuteScriptAtInstanceShutdown, filter); 119 RUN_TEST(SetupExecuteScriptAtInstanceShutdown, filter);
151 RUN_TEST(ExecuteScriptAtInstanceShutdown, filter); 120 RUN_TEST(ExecuteScriptAtInstanceShutdown, filter);
152 } 121 }
153 122
154 void TestInstance::LeakReferenceAndIgnore(const pp::Var& leaked) { 123 void TestInstance::LeakReferenceAndIgnore(const pp::Var& leaked) {
155 static const PPB_Var* var_interface = static_cast<const PPB_Var*>( 124 static const PPB_Var* var_interface = static_cast<const PPB_Var*>(
156 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); 125 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
157 var_interface->AddRef(leaked.pp_var()); 126 var_interface->AddRef(leaked.pp_var());
158 IgnoreLeakedVar(leaked.pp_var().value.as_id); 127 IgnoreLeakedVar(leaked.pp_var().value.as_id);
159 } 128 }
160 129
161 pp::deprecated::ScriptableObject* TestInstance::CreateTestObject() { 130 pp::deprecated::ScriptableObject* TestInstance::CreateTestObject() {
162 return new InstanceSO(this); 131 if (!instance_so_)
132 instance_so_ = new InstanceSO(this);
133 return instance_so_;
163 } 134 }
164 135
165 std::string TestInstance::TestExecuteScript() { 136 std::string TestInstance::TestExecuteScript() {
166 // Simple call back into the plugin. 137 // Simple call back into the plugin.
167 pp::Var exception; 138 pp::Var exception;
168 pp::Var ret = instance_->ExecuteScript( 139 pp::Var ret = instance_->ExecuteScript(
169 "document.getElementById('plugin').SetValue('hello, world');", 140 "document.getElementById('plugin').SetValue('hello, world');",
170 &exception); 141 &exception);
171 ASSERT_TRUE(ret.is_undefined()); 142 ASSERT_TRUE(ret.is_undefined());
172 ASSERT_TRUE(exception.is_undefined()); 143 ASSERT_TRUE(exception.is_undefined());
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 // that it was set as expected. 263 // that it was set as expected.
293 pp::Var result = instance()->ExecuteScript( 264 pp::Var result = instance()->ExecuteScript(
294 "sessionStorage.getItem('instance_destroyed');"); 265 "sessionStorage.getItem('instance_destroyed');");
295 ASSERT_TRUE(result.is_string()); 266 ASSERT_TRUE(result.is_string());
296 ASSERT_EQ(std::string("true"), result.AsString()); 267 ASSERT_EQ(std::string("true"), result.AsString());
297 instance()->ExecuteScript("sessionStorage.removeItem('instance_destroyed');"); 268 instance()->ExecuteScript("sessionStorage.removeItem('instance_destroyed');");
298 269
299 PASS(); 270 PASS();
300 } 271 }
301 272
OLDNEW
« no previous file with comments | « ppapi/tests/test_instance_deprecated.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698