Chromium Code Reviews| Index: ppapi/tests/test_instance_deprecated.cc |
| diff --git a/ppapi/tests/test_instance_deprecated.cc b/ppapi/tests/test_instance_deprecated.cc |
| index 6746858e2a9edb6fbe8f2d1141e995c0584f5cb8..8cbd5c308306d1e01d4cd26849ec34d8d33fc131 100644 |
| --- a/ppapi/tests/test_instance_deprecated.cc |
| +++ b/ppapi/tests/test_instance_deprecated.cc |
| @@ -17,63 +17,16 @@ static const char kSetValueFunction[] = "SetValue"; |
| static const char kSetExceptionFunction[] = "SetException"; |
| static const char kReturnValueFunction[] = "ReturnValue"; |
| -// ScriptableObject used by instance. |
| -class InstanceSO : public pp::deprecated::ScriptableObject { |
| - public: |
| - explicit InstanceSO(TestInstance* i); |
| - virtual ~InstanceSO(); |
| - |
| - // pp::deprecated::ScriptableObject overrides. |
| - bool HasMethod(const pp::Var& name, pp::Var* exception); |
| - pp::Var Call(const pp::Var& name, |
| - const std::vector<pp::Var>& args, |
| - pp::Var* exception); |
| - |
| - private: |
| - TestInstance* test_instance_; |
| - // For out-of-process, the InstanceSO might be deleted after the instance was |
| - // already destroyed, so we can't rely on test_instance_->testing_interface() |
| - // being valid. Therefore we store our own. |
| - const PPB_Testing_Private* testing_interface_; |
| -}; |
| - |
| InstanceSO::InstanceSO(TestInstance* i) |
| : test_instance_(i), |
| testing_interface_(i->testing_interface()) { |
| - // Set up a post-condition for the test so that we can ensure our destructor |
| - // is called. This only works reliably in-process. Out-of-process, it only |
| - // can work when the renderer stays alive a short while after the plugin |
| - // instance is destroyed. If the renderer is being shut down, too much happens |
| - // asynchronously for the out-of-process case to work reliably. In |
| - // particular: |
| - // - The Var ReleaseObject message is asynchronous. |
| - // - The PPB_Var_Deprecated host-side proxy posts a task to actually release |
| - // the object when the ReleaseObject message is received. |
| - // - The PPP_Class Deallocate message is asynchronous. |
| - // At time of writing this comment, if you modify the code so that the above |
| - // happens synchronously, and you remove the restriction that the plugin can't |
| - // be unblocked by a sync message, then this check actually passes reliably |
| - // for out-of-process. But we don't want to make any of those changes, so we |
| - // just skip the check. |
| - if (testing_interface_->IsOutOfProcess() == PP_FALSE) { |
| - i->instance()->AddPostCondition( |
| - "window.document.getElementById('container').instance_object_destroyed" |
| - ); |
| - } |
| + if (testing_interface_->IsOutOfProcess() == PP_FALSE) |
| + test_instance_->set_instance_object_destroyed(false); |
| } |
| InstanceSO::~InstanceSO() { |
| - if (testing_interface_->IsOutOfProcess() == PP_FALSE) { |
| - // TODO(dmichael): It would probably be best to make in-process consistent |
| - // with out-of-process. That would mean that the instance |
| - // would already be destroyed at this point. |
| - pp::Var ret = test_instance_->instance()->ExecuteScript( |
| - "document.getElementById('container').instance_object_destroyed=true;"); |
| - } else { |
| - // Out-of-process, this destructor might not actually get invoked. See the |
| - // comment in InstanceSO's constructor for an explanation. Also, instance() |
| - // has already been destroyed :-(. So we can't really do anything here. |
| - } |
| + if (test_instance_) |
| + test_instance_->set_instance_object_destroyed(true); |
| } |
| bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) { |
| @@ -94,7 +47,7 @@ pp::Var InstanceSO::Call(const pp::Var& method_name, |
| if (name == kSetValueFunction) { |
| if (args.size() != 1 || !args[0].is_string()) |
| *exception = pp::Var("Bad argument to SetValue(<string>)"); |
| - else |
| + else if (test_instance_) |
| test_instance_->set_string(args[0].AsString()); |
| } else if (name == kSetExceptionFunction) { |
| if (args.size() != 1 || !args[0].is_string()) |
| @@ -117,8 +70,9 @@ pp::Var InstanceSO::Call(const pp::Var& method_name, |
| REGISTER_TEST_CASE(Instance); |
| -TestInstance::TestInstance(TestingInstance* instance) : TestCase(instance) { |
| -} |
| +TestInstance::TestInstance(TestingInstance* instance) |
| + : TestCase(instance), |
| + instance_so_(NULL) {} |
| bool TestInstance::Init() { |
| return true; |
| @@ -126,11 +80,33 @@ bool TestInstance::Init() { |
| TestInstance::~TestInstance() { |
| ResetTestObject(); |
| - // When running tests in process, some post conditions check that teardown |
| - // happened successfully. We need to run the garbage collector to ensure that |
| - // vars get released. |
| - if (testing_interface_->IsOutOfProcess() == PP_FALSE) |
| + if (testing_interface_->IsOutOfProcess() == PP_FALSE) { |
| + // This should cause the instance objects descructor to be called. |
|
Sam McNally
2014/08/27 04:45:51
objects descructor -> object's destructor
|
| testing_interface_->RunV8GC(instance_->pp_instance()); |
| + |
| + // Test a post-condition which ensures the instance objects destructor is |
| + // called. This only works reliably in-process. Out-of-process, it only |
| + // can work when the renderer stays alive a short while after the plugin |
| + // instance is destroyed. If the renderer is being shut down, too much |
| + // happens asynchronously for the out-of-process case to work reliably. In |
| + // particular: |
| + // - The Var ReleaseObject message is asynchronous. |
| + // - The PPB_Var_Deprecated host-side proxy posts a task to actually |
| + // release the object when the ReleaseObject message is received. |
| + // - The PPP_Class Deallocate message is asynchronous. |
| + // At time of writing this comment, if you modify the code so that the above |
| + // happens synchronously, and you remove the restriction that the plugin |
| + // can't be unblocked by a sync message, then this check actually passes |
| + // reliably for out-of-process. But we don't want to make any of those |
| + // changes so we just skip the check. |
| + PP_DCHECK(!instance_so_); |
| + } else { |
| + // Out-of-process, this destructor might not actually get invoked. Clear |
| + // the InstanceSOs reference to the instance so there is no UAF. |
| + if (instance_so_) |
| + instance_so_->clear_test_instance(); |
| + } |
| + |
| // Save the fact that we were destroyed in sessionStorage. This tests that |
| // we can ExecuteScript at instance destruction without crashing. It also |
| // allows us to check that ExecuteScript will run and succeed in certain |
| @@ -159,7 +135,9 @@ void TestInstance::LeakReferenceAndIgnore(const pp::Var& leaked) { |
| } |
| pp::deprecated::ScriptableObject* TestInstance::CreateTestObject() { |
| - return new InstanceSO(this); |
| + if (!instance_so_) |
| + instance_so_ = new InstanceSO(this); |
| + return instance_so_; |
| } |
| std::string TestInstance::TestExecuteScript() { |