OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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. | |
4 | |
5 #include "content/test/plugin/plugin_delete_plugin_in_deallocate_test.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/compiler_specific.h" | |
9 | |
10 namespace { | |
11 | |
12 NPAPIClient::DeletePluginInDeallocateTest* g_signalling_instance_ = NULL; | |
13 | |
14 class DeletePluginInDeallocateTestNPObject : public NPObject { | |
15 public: | |
16 DeletePluginInDeallocateTestNPObject() | |
17 : NPObject(), id_(NULL), host_functions_(NULL), deallocate_count_(0) {} | |
18 | |
19 static NPObject* Allocate(NPP npp, NPClass* npclass) { | |
20 return new DeletePluginInDeallocateTestNPObject(); | |
21 } | |
22 | |
23 static void Deallocate(NPObject* npobject) { | |
24 DeletePluginInDeallocateTestNPObject* object = | |
25 reinterpret_cast<DeletePluginInDeallocateTestNPObject*>(npobject); | |
26 ++object->deallocate_count_; | |
27 | |
28 // Call window.deletePlugin to tear-down our plugin from inside deallocate. | |
29 if (object->deallocate_count_ == 1) { | |
30 NPIdentifier delete_id = | |
31 object->host_functions_->getstringidentifier("deletePlugin"); | |
32 NPObject* window_obj = NULL; | |
33 object->host_functions_->getvalue(object->id_, NPNVWindowNPObject, | |
34 &window_obj); | |
35 NPVariant rv; | |
36 object->host_functions_->invoke(object->id_, window_obj, delete_id, NULL, | |
37 0, &rv); | |
38 } | |
39 } | |
40 | |
41 NPP id_; | |
42 NPNetscapeFuncs* host_functions_; | |
43 int deallocate_count_; | |
44 }; | |
45 | |
46 NPClass* GetDeletePluginInDeallocateTestClass() { | |
47 static NPClass plugin_class = { | |
48 NP_CLASS_STRUCT_VERSION, | |
49 DeletePluginInDeallocateTestNPObject::Allocate, | |
50 DeletePluginInDeallocateTestNPObject::Deallocate, | |
51 NULL, // Invalidate | |
52 NULL, // HasMethod | |
53 NULL, // Invoke | |
54 NULL, // InvokeDefault | |
55 NULL, // HasProperty | |
56 NULL, // GetProperty | |
57 NULL, // SetProperty | |
58 NULL, // RemoveProperty | |
59 }; | |
60 return &plugin_class; | |
61 } | |
62 | |
63 } // namespace | |
64 | |
65 namespace NPAPIClient { | |
66 | |
67 DeletePluginInDeallocateTest::DeletePluginInDeallocateTest( | |
68 NPP id, NPNetscapeFuncs* host_functions) | |
69 : PluginTest(id, host_functions), npobject_(NULL), test_started_(false) { | |
70 } | |
71 | |
72 NPError DeletePluginInDeallocateTest::SetWindow(NPWindow* pNPWindow) { | |
73 #if !defined(OS_MACOSX) | |
74 if (pNPWindow->window == NULL) | |
75 return NPERR_NO_ERROR; | |
76 #endif | |
77 | |
78 // Ensure that we run the test once, even if SetWindow is called again. | |
79 if (test_started_) | |
80 return NPERR_NO_ERROR; | |
81 test_started_ = true; | |
82 | |
83 // Because of http://crbug.com/94829, we have to have a second plugin | |
84 // instance that we can use to signal completion. | |
85 if (test_id() == "signaller") { | |
86 g_signalling_instance_ = this; | |
87 return NPERR_NO_ERROR; | |
88 } | |
89 | |
90 // Create a custom NPObject and give our Id and the Netscape function table. | |
91 npobject_ = HostFunctions()->createobject( | |
92 id(), GetDeletePluginInDeallocateTestClass()); | |
93 DeletePluginInDeallocateTestNPObject* test_object = | |
94 reinterpret_cast<DeletePluginInDeallocateTestNPObject*>(npobject_); | |
95 test_object->id_ = id(); | |
96 test_object->host_functions_ = HostFunctions(); | |
97 | |
98 // Fetch the window script object for our page. | |
99 NPObject* window = NULL; | |
100 HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window); | |
101 | |
102 // Pass it to the window.setTestObject function, which will later release it. | |
103 NPIdentifier set_test_object_id = | |
104 HostFunctions()->getstringidentifier("setTestObject"); | |
105 NPVariant func_var; | |
106 NULL_TO_NPVARIANT(func_var); | |
107 HostFunctions()->getproperty(id(), window, set_test_object_id, &func_var); | |
108 | |
109 NPObject* func = NPVARIANT_TO_OBJECT(func_var); | |
110 NPVariant func_arg; | |
111 OBJECT_TO_NPVARIANT(npobject_, func_arg); | |
112 NPVariant func_result; | |
113 HostFunctions()->invokeDefault(id(), func, &func_arg, 1, | |
114 &func_result); | |
115 | |
116 // Release the object - the page's reference should keep it alive. | |
117 HostFunctions()->releaseobject(npobject_); | |
118 | |
119 return NPERR_NO_ERROR; | |
120 } | |
121 | |
122 NPError DeletePluginInDeallocateTest::Destroy() { | |
123 // Because of http://crbug.com/94829, we can't signal completion from within | |
124 // the NPP_Destroy of the plugin that is being destroyed. We work-around | |
125 // that by testing using a second instance, and signalling though the main | |
126 // test instance. | |
127 | |
128 // There should always be a signalling instance by the time we reach here. | |
129 if (!g_signalling_instance_) | |
130 return NPERR_NO_ERROR; | |
131 | |
132 // If we're the signalling instance, do nothing. | |
133 if (g_signalling_instance_ == this) | |
134 return NPERR_NO_ERROR; | |
135 | |
136 if (!npobject_) { | |
137 g_signalling_instance_->SetError("SetWindow was not invoked."); | |
138 } else { | |
139 // Verify that our object was deallocated exactly once. | |
140 DeletePluginInDeallocateTestNPObject* test_object = | |
141 reinterpret_cast<DeletePluginInDeallocateTestNPObject*>(npobject_); | |
142 if (test_object->deallocate_count_ != 1) | |
143 g_signalling_instance_->SetError( | |
144 "Object was not deallocated exactly once."); | |
145 delete test_object; | |
146 } | |
147 | |
148 g_signalling_instance_->SignalTestCompleted(); | |
149 | |
150 return NPERR_NO_ERROR; | |
151 } | |
152 | |
153 } // namespace NPAPIClient | |
OLD | NEW |