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..e4235b84878451e95550095de6a51e73fd6383cb 100644 |
--- a/ppapi/tests/test_instance_deprecated.cc |
+++ b/ppapi/tests/test_instance_deprecated.cc |
@@ -8,72 +8,20 @@ |
#include "ppapi/c/ppb_var.h" |
#include "ppapi/cpp/module.h" |
-#include "ppapi/cpp/dev/scriptable_object_deprecated.h" |
#include "ppapi/tests/testing_instance.h" |
-namespace { |
- |
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" |
- ); |
- } |
} |
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_->clear_instance_so(); |
} |
bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) { |
@@ -94,7 +42,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()) |
@@ -113,12 +61,11 @@ pp::Var InstanceSO::Call(const pp::Var& method_name, |
return pp::Var(); |
} |
-} // namespace |
- |
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 +73,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 object's descructor to be called. |
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 +128,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() { |