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.
5 #include "content/test/plugin/plugin_delete_plugin_in_deallocate_test.h"
7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h"
12 NPAPIClient::DeletePluginInDeallocateTest
* g_signalling_instance_
= NULL
;
14 class DeletePluginInDeallocateTestNPObject
: public NPObject
{
16 DeletePluginInDeallocateTestNPObject()
17 : NPObject(), id_(NULL
), host_functions_(NULL
), deallocate_count_(0) {}
19 static NPObject
* Allocate(NPP npp
, NPClass
* npclass
) {
20 return new DeletePluginInDeallocateTestNPObject();
23 static void Deallocate(NPObject
* npobject
) {
24 DeletePluginInDeallocateTestNPObject
* object
=
25 reinterpret_cast<DeletePluginInDeallocateTestNPObject
*>(npobject
);
26 ++object
->deallocate_count_
;
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
,
36 object
->host_functions_
->invoke(object
->id_
, window_obj
, delete_id
, NULL
,
42 NPNetscapeFuncs
* host_functions_
;
43 int deallocate_count_
;
46 NPClass
* GetDeletePluginInDeallocateTestClass() {
47 static NPClass plugin_class
= {
48 NP_CLASS_STRUCT_VERSION
,
49 DeletePluginInDeallocateTestNPObject::Allocate
,
50 DeletePluginInDeallocateTestNPObject::Deallocate
,
54 NULL
, // InvokeDefault
58 NULL
, // RemoveProperty
65 namespace NPAPIClient
{
67 DeletePluginInDeallocateTest::DeletePluginInDeallocateTest(
68 NPP id
, NPNetscapeFuncs
* host_functions
)
69 : PluginTest(id
, host_functions
), npobject_(NULL
), test_started_(false) {
72 NPError
DeletePluginInDeallocateTest::SetWindow(NPWindow
* pNPWindow
) {
73 #if !defined(OS_MACOSX)
74 if (pNPWindow
->window
== NULL
)
75 return NPERR_NO_ERROR
;
78 // Ensure that we run the test once, even if SetWindow is called again.
80 return NPERR_NO_ERROR
;
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
;
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();
98 // Fetch the window script object for our page.
99 NPObject
* window
= NULL
;
100 HostFunctions()->getvalue(id(), NPNVWindowNPObject
, &window
);
102 // Pass it to the window.setTestObject function, which will later release it.
103 NPIdentifier set_test_object_id
=
104 HostFunctions()->getstringidentifier("setTestObject");
106 NULL_TO_NPVARIANT(func_var
);
107 HostFunctions()->getproperty(id(), window
, set_test_object_id
, &func_var
);
109 NPObject
* func
= NPVARIANT_TO_OBJECT(func_var
);
111 OBJECT_TO_NPVARIANT(npobject_
, func_arg
);
112 NPVariant func_result
;
113 HostFunctions()->invokeDefault(id(), func
, &func_arg
, 1,
116 // Release the object - the page's reference should keep it alive.
117 HostFunctions()->releaseobject(npobject_
);
119 return NPERR_NO_ERROR
;
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
128 // There should always be a signalling instance by the time we reach here.
129 if (!g_signalling_instance_
)
130 return NPERR_NO_ERROR
;
132 // If we're the signalling instance, do nothing.
133 if (g_signalling_instance_
== this)
134 return NPERR_NO_ERROR
;
137 g_signalling_instance_
->SetError("SetWindow was not invoked.");
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.");
148 g_signalling_instance_
->SignalTestCompleted();
150 return NPERR_NO_ERROR
;
153 } // namespace NPAPIClient