1 // Copyright (c) 2010 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_npobject_lifetime_test.h"
7 namespace NPAPIClient
{
9 const int kNPObjectLifetimeTimer
= 100;
10 const int kNPObjectLifetimeTimerElapse
= 2000;
12 NPObject
* NPObjectLifetimeTestInstance2::plugin_instance_object_
= NULL
;
14 NPObjectDeletePluginInNPN_Evaluate
*
15 NPObjectDeletePluginInNPN_Evaluate::g_npn_evaluate_test_instance_
= NULL
;
17 NPObjectLifetimeTest::NPObjectLifetimeTest(NPP id
,
18 NPNetscapeFuncs
*host_functions
)
19 : PluginTest(id
, host_functions
),
20 other_plugin_instance_object_(NULL
),
24 NPError
NPObjectLifetimeTest::SetWindow(NPWindow
* pNPWindow
) {
25 if (pNPWindow
->window
== NULL
)
26 return NPERR_NO_ERROR
;
28 HWND window_handle
= reinterpret_cast<HWND
>(pNPWindow
->window
);
29 if (!::GetProp(window_handle
, L
"Plugin_Instance")) {
30 // TODO: this propery leaks.
31 ::SetProp(window_handle
, L
"Plugin_Instance", this);
32 // We attempt to retreive the NPObject for the plugin instance identified
33 // by the NPObjectLifetimeTestInstance2 class as it may not have been
35 timer_id_
= SetTimer(window_handle
, kNPObjectLifetimeTimer
,
36 kNPObjectLifetimeTimerElapse
, TimerProc
);
38 return NPERR_NO_ERROR
;
41 void CALLBACK
NPObjectLifetimeTest::TimerProc(
42 HWND window
, UINT message
, UINT_PTR timer_id
,
43 DWORD elapsed_milli_seconds
) {
45 NPObjectLifetimeTest
* this_instance
=
46 reinterpret_cast<NPObjectLifetimeTest
*>
47 (::GetProp(window
, L
"Plugin_Instance"));
48 KillTimer(window
, this_instance
->timer_id_
);
49 ::RemoveProp(window
, L
"Plugin_Instance");
51 this_instance
->timer_id_
= 0;
53 this_instance
->other_plugin_instance_object_
=
54 NPObjectLifetimeTestInstance2::plugin_instance_object_
;
55 this_instance
->HostFunctions()->retainobject(
56 this_instance
->other_plugin_instance_object_
);
59 script
.UTF8Characters
= "javascript:DeleteSecondPluginInstance()";
60 script
.UTF8Length
= static_cast<uint32_t>(strlen(script
.UTF8Characters
));
62 this_instance
->HostFunctions()->geturlnotify(
63 this_instance
->id(), "javascript:DeleteSecondPluginInstance()", NULL
,
64 reinterpret_cast<void*>(1));
67 void NPObjectLifetimeTest::URLNotify(const char* url
, NPReason reason
,
69 // Create a "location" identifier.
70 NPIdentifier identifier
= HostFunctions()->getstringidentifier("location");
71 // Declare a local variant value.
72 NPVariant variantValue
;
73 // Get the location property from the window object (which is another object).
74 bool b1
= HostFunctions()->getproperty(id(), other_plugin_instance_object_
,
75 identifier
, &variantValue
);
76 HostFunctions()->releaseobject(other_plugin_instance_object_
);
77 other_plugin_instance_object_
= NULL
;
78 // If this test failed, then we'd have crashed by now.
79 SignalTestCompleted();
82 NPObjectLifetimeTestInstance2::NPObjectLifetimeTestInstance2(
83 NPP id
, NPNetscapeFuncs
*host_functions
)
84 : PluginTest(id
, host_functions
) {
87 NPObjectLifetimeTestInstance2::~NPObjectLifetimeTestInstance2() {
88 if (plugin_instance_object_
) {
89 HostFunctions()->releaseobject(plugin_instance_object_
);
90 plugin_instance_object_
= NULL
;
94 NPError
NPObjectLifetimeTestInstance2::SetWindow(NPWindow
* pNPWindow
) {
95 if (pNPWindow
->window
== NULL
)
96 return NPERR_NO_ERROR
;
98 if (!plugin_instance_object_
) {
99 if (!HostFunctions()->getvalue(id(), NPNVWindowNPObject
,
100 &plugin_instance_object_
)) {
101 SetError("Failed to get NPObject for plugin instance2");
102 SignalTestCompleted();
103 return NPERR_GENERIC_ERROR
;
107 return NPERR_NO_ERROR
;
111 NPObjectDeletePluginInNPN_Evaluate::NPObjectDeletePluginInNPN_Evaluate(
112 NPP id
, NPNetscapeFuncs
*host_functions
)
113 : PluginTest(id
, host_functions
),
114 plugin_instance_object_(NULL
),
116 g_npn_evaluate_test_instance_
= this;
119 NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() {
120 if (plugin_instance_object_
) {
121 HostFunctions()->releaseobject(plugin_instance_object_
);
122 plugin_instance_object_
= NULL
;
126 NPError
NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow
* np_window
) {
127 if (np_window
->window
== NULL
)
128 return NPERR_NO_ERROR
;
130 HWND window_handle
= reinterpret_cast<HWND
>(np_window
->window
);
131 // We setup a timerproc to invoke NPN_Evaluate to destroy this plugin
132 // instance. This is to ensure that we don't destroy the plugin instance
133 // while it is being used in webkit as this leads to crashes and is a
134 // more accurate representation of the renderer crash as described in
135 // http://b/issue?id=1134683.
137 timer_id_
= SetTimer(window_handle
, kNPObjectLifetimeTimer
,
138 kNPObjectLifetimeTimerElapse
, TimerProc
);
140 return NPERR_NO_ERROR
;
143 void CALLBACK
NPObjectDeletePluginInNPN_Evaluate::TimerProc(
144 HWND window
, UINT message
, UINT_PTR timer_id
,
145 DWORD elapsed_milli_seconds
) {
147 KillTimer(window
, g_npn_evaluate_test_instance_
->timer_id_
);
148 g_npn_evaluate_test_instance_
->timer_id_
= 0;
149 NPObject
*window_obj
= NULL
;
150 g_npn_evaluate_test_instance_
->HostFunctions()->getvalue(
151 g_npn_evaluate_test_instance_
->id(), NPNVWindowNPObject
,
155 g_npn_evaluate_test_instance_
->SetError(
156 "Failed to get NPObject for plugin instance2");
157 g_npn_evaluate_test_instance_
->SignalTestCompleted();
161 std::string script
= "javascript:DeletePluginWithinScript()";
162 NPString script_string
;
163 script_string
.UTF8Characters
= script
.c_str();
164 script_string
.UTF8Length
=
165 static_cast<unsigned int>(script
.length());
167 NPVariant result_var
;
168 bool result
= g_npn_evaluate_test_instance_
->HostFunctions()->evaluate(
169 g_npn_evaluate_test_instance_
->id(), window_obj
,
170 &script_string
, &result_var
);
171 // If this test failed we would have crashed by now.
174 } // namespace NPAPIClient