Make certificate viewer a tab-modal dialog.
[chromium-blink-merge.git] / ppapi / tests / test_instance_deprecated.cc
blob72e1fad0717a95f67be9d09a91eeccc7e2aa752b
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
3 // found in the LICENSE file.
5 #include "ppapi/tests/test_instance_deprecated.h"
7 #include <assert.h>
9 #include "ppapi/c/ppb_var.h"
10 #include "ppapi/cpp/module.h"
11 #include "ppapi/cpp/dev/scriptable_object_deprecated.h"
12 #include "ppapi/tests/testing_instance.h"
14 namespace {
16 static const char kSetValueFunction[] = "SetValue";
17 static const char kSetExceptionFunction[] = "SetException";
18 static const char kReturnValueFunction[] = "ReturnValue";
20 // ScriptableObject used by instance.
21 class InstanceSO : public pp::deprecated::ScriptableObject {
22 public:
23 InstanceSO(TestInstance* i);
24 virtual ~InstanceSO();
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);
32 private:
33 TestInstance* test_instance_;
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"
51 InstanceSO::~InstanceSO() {
52 pp::Var exception;
53 pp::Var ret = test_instance_->instance()->ExecuteScript(
54 "document.getElementById('container').instance_object_destroyed=true;");
57 bool InstanceSO::HasMethod(const pp::Var& name, pp::Var* exception) {
58 if (!name.is_string())
59 return false;
60 return name.AsString() == kSetValueFunction ||
61 name.AsString() == kSetExceptionFunction ||
62 name.AsString() == kReturnValueFunction;
65 pp::Var InstanceSO::Call(const pp::Var& method_name,
66 const std::vector<pp::Var>& args,
67 pp::Var* exception) {
68 if (!method_name.is_string())
69 return false;
70 std::string name = method_name.AsString();
72 if (name == kSetValueFunction) {
73 if (args.size() != 1 || !args[0].is_string())
74 *exception = pp::Var("Bad argument to SetValue(<string>)");
75 else
76 test_instance_->set_string(args[0].AsString());
77 } else if (name == kSetExceptionFunction) {
78 if (args.size() != 1 || !args[0].is_string())
79 *exception = pp::Var("Bad argument to SetException(<string>)");
80 else
81 *exception = args[0];
82 } else if (name == kReturnValueFunction) {
83 if (args.size() != 1)
84 *exception = pp::Var("Need single arg to call ReturnValue");
85 else
86 return args[0];
87 } else {
88 *exception = pp::Var("Bad function call");
91 return pp::Var();
94 } // namespace
96 REGISTER_TEST_CASE(Instance);
98 TestInstance::TestInstance(TestingInstance* instance) : TestCase(instance) {
101 bool TestInstance::Init() {
102 return true;
105 void TestInstance::RunTests(const std::string& filter) {
106 RUN_TEST(ExecuteScript, filter);
107 RUN_TEST(RecursiveObjects, filter);
108 RUN_TEST(LeakedObjectDestructors, filter);
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);
118 pp::deprecated::ScriptableObject* TestInstance::CreateTestObject() {
119 return new InstanceSO(this);
122 std::string TestInstance::TestExecuteScript() {
123 // Simple call back into the plugin.
124 pp::Var exception;
125 pp::Var ret = instance_->ExecuteScript(
126 "document.getElementById('plugin').SetValue('hello, world');",
127 &exception);
128 ASSERT_TRUE(ret.is_undefined());
129 ASSERT_TRUE(exception.is_undefined());
130 ASSERT_TRUE(string_ == "hello, world");
132 // Return values from the plugin should be returned.
133 ret = instance_->ExecuteScript(
134 "document.getElementById('plugin').ReturnValue('return value');",
135 &exception);
136 ASSERT_TRUE(ret.is_string() && ret.AsString() == "return value");
137 ASSERT_TRUE(exception.is_undefined());
139 // Exception thrown by the plugin should be caught.
140 ret = instance_->ExecuteScript(
141 "document.getElementById('plugin').SetException('plugin exception');",
142 &exception);
143 ASSERT_TRUE(ret.is_undefined());
144 ASSERT_TRUE(exception.is_string());
145 // Due to a limitation in the implementation of TryCatch, it doesn't actually
146 // pass the strings up. Since this is a trusted only interface, we've decided
147 // not to bother fixing this for now.
149 // Exception caused by string evaluation should be caught.
150 exception = pp::Var();
151 ret = instance_->ExecuteScript("document.doesntExist()", &exception);
152 ASSERT_TRUE(ret.is_undefined());
153 ASSERT_TRUE(exception.is_string()); // Don't know exactly what it will say.
155 PASS();
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));
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);
178 private:
179 pp::VarPrivate child_;
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));
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);
199 PASS();
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);
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();