OLD | NEW |
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" |
(...skipping 22 matching lines...) Expand all Loading... |
33 TestInstance* test_instance_; | 33 TestInstance* test_instance_; |
34 // For out-of-process, the InstanceSO might be deleted after the instance was | 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() | 35 // already destroyed, so we can't rely on test_instance_->testing_interface() |
36 // being valid. Therefore we store our own. | 36 // being valid. Therefore we store our own. |
37 const PPB_Testing_Private* testing_interface_; | 37 const PPB_Testing_Private* testing_interface_; |
38 }; | 38 }; |
39 | 39 |
40 InstanceSO::InstanceSO(TestInstance* i) | 40 InstanceSO::InstanceSO(TestInstance* i) |
41 : test_instance_(i), | 41 : test_instance_(i), |
42 testing_interface_(i->testing_interface()) { | 42 testing_interface_(i->testing_interface()) { |
43 if (testing_interface_->IsOutOfProcess() == PP_FALSE) | 43 // Set up a post-condition for the test so that we can ensure our destructor |
44 test_instance_->set_instance_object_destroyed(false); | 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 } |
45 } | 63 } |
46 | 64 |
47 InstanceSO::~InstanceSO() { | 65 InstanceSO::~InstanceSO() { |
48 test_instance_->set_instance_object_destroyed(true); | 66 if (testing_interface_->IsOutOfProcess() == PP_FALSE) { |
| 67 // TODO(dmichael): It would probably be best to make in-process consistent |
| 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 } |
49 } | 77 } |
50 | 78 |
51 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) { | 79 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) { |
52 if (!name.is_string()) | 80 if (!name.is_string()) |
53 return false; | 81 return false; |
54 return name.AsString() == kSetValueFunction || | 82 return name.AsString() == kSetValueFunction || |
55 name.AsString() == kSetExceptionFunction || | 83 name.AsString() == kSetExceptionFunction || |
56 name.AsString() == kReturnValueFunction; | 84 name.AsString() == kReturnValueFunction; |
57 } | 85 } |
58 | 86 |
(...skipping 23 matching lines...) Expand all Loading... |
82 *exception = pp::Var("Bad function call"); | 110 *exception = pp::Var("Bad function call"); |
83 } | 111 } |
84 | 112 |
85 return pp::Var(); | 113 return pp::Var(); |
86 } | 114 } |
87 | 115 |
88 } // namespace | 116 } // namespace |
89 | 117 |
90 REGISTER_TEST_CASE(Instance); | 118 REGISTER_TEST_CASE(Instance); |
91 | 119 |
92 TestInstance::TestInstance(TestingInstance* instance) | 120 TestInstance::TestInstance(TestingInstance* instance) : TestCase(instance) { |
93 : TestCase(instance), | 121 } |
94 instance_object_destroyed_(false) {} | |
95 | 122 |
96 bool TestInstance::Init() { | 123 bool TestInstance::Init() { |
97 return true; | 124 return true; |
98 } | 125 } |
99 | 126 |
100 TestInstance::~TestInstance() { | 127 TestInstance::~TestInstance() { |
101 ResetTestObject(); | 128 ResetTestObject(); |
102 if (testing_interface_->IsOutOfProcess() == PP_FALSE) { | 129 // When running tests in process, some post conditions check that teardown |
103 // This should cause the instance objects descructor to be called. | 130 // happened successfully. We need to run the garbage collector to ensure that |
| 131 // vars get released. |
| 132 if (testing_interface_->IsOutOfProcess() == PP_FALSE) |
104 testing_interface_->RunV8GC(instance_->pp_instance()); | 133 testing_interface_->RunV8GC(instance_->pp_instance()); |
105 | |
106 // Test a post-condition which ensures the instance objects destructor is | |
107 // called. This only works reliably in-process. Out-of-process, it only | |
108 // can work when the renderer stays alive a short while after the plugin | |
109 // instance is destroyed. If the renderer is being shut down, too much | |
110 // happens asynchronously for the out-of-process case to work reliably. In | |
111 // particular: | |
112 // - The Var ReleaseObject message is asynchronous. | |
113 // - The PPB_Var_Deprecated host-side proxy posts a task to actually | |
114 // release the object when the ReleaseObject message is received. | |
115 // - The PPP_Class Deallocate message is asynchronous. | |
116 // At time of writing this comment, if you modify the code so that the above | |
117 // happens synchronously, and you remove the restriction that the plugin | |
118 // can't be unblocked by a sync message, then this check actually passes | |
119 // reliably for out-of-process. But we don't want to make any of those | |
120 // changes so we just skip the check. | |
121 PP_DCHECK(instance_object_destroyed_); | |
122 } else { | |
123 // Out-of-process, this destructor might not actually get invoked. See the | |
124 // comment in InstanceSO's constructor for an explanation. Also, instance() | |
125 // has already been destroyed :-(. So we can't really do anything here. | |
126 } | |
127 | |
128 // Save the fact that we were destroyed in sessionStorage. This tests that | 134 // Save the fact that we were destroyed in sessionStorage. This tests that |
129 // we can ExecuteScript at instance destruction without crashing. It also | 135 // we can ExecuteScript at instance destruction without crashing. It also |
130 // allows us to check that ExecuteScript will run and succeed in certain | 136 // allows us to check that ExecuteScript will run and succeed in certain |
131 // cases. In particular, when the instance is destroyed by normal DOM | 137 // cases. In particular, when the instance is destroyed by normal DOM |
132 // deletion, ExecuteScript will actually work. See | 138 // deletion, ExecuteScript will actually work. See |
133 // TestExecuteScriptInInstanceShutdown for that test. Note, however, that | 139 // TestExecuteScriptInInstanceShutdown for that test. Note, however, that |
134 // ExecuteScript will *not* have an effect when the instance is destroyed | 140 // ExecuteScript will *not* have an effect when the instance is destroyed |
135 // because the renderer was shut down. | 141 // because the renderer was shut down. |
136 pp::Var ret = instance()->ExecuteScript( | 142 pp::Var ret = instance()->ExecuteScript( |
137 "sessionStorage.setItem('instance_destroyed', 'true');"); | 143 "sessionStorage.setItem('instance_destroyed', 'true');"); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 // that it was set as expected. | 292 // that it was set as expected. |
287 pp::Var result = instance()->ExecuteScript( | 293 pp::Var result = instance()->ExecuteScript( |
288 "sessionStorage.getItem('instance_destroyed');"); | 294 "sessionStorage.getItem('instance_destroyed');"); |
289 ASSERT_TRUE(result.is_string()); | 295 ASSERT_TRUE(result.is_string()); |
290 ASSERT_EQ(std::string("true"), result.AsString()); | 296 ASSERT_EQ(std::string("true"), result.AsString()); |
291 instance()->ExecuteScript("sessionStorage.removeItem('instance_destroyed');"); | 297 instance()->ExecuteScript("sessionStorage.removeItem('instance_destroyed');"); |
292 | 298 |
293 PASS(); | 299 PASS(); |
294 } | 300 } |
295 | 301 |
OLD | NEW |