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. 4 5 #include "content/test/plugin/plugin_npobject_lifetime_test.h" 6 7 namespace NPAPIClient { 8 9 const int kNPObjectLifetimeTimer = 100; 10 const int kNPObjectLifetimeTimerElapse = 2000; 11 12 NPObject* NPObjectLifetimeTestInstance2::plugin_instance_object_ = NULL; 13 14 NPObjectDeletePluginInNPN_Evaluate* 15 NPObjectDeletePluginInNPN_Evaluate::g_npn_evaluate_test_instance_ = NULL; 16 17 NPObjectLifetimeTest::NPObjectLifetimeTest(NPP id, 18 NPNetscapeFuncs *host_functions) 19 : PluginTest(id, host_functions), 20 other_plugin_instance_object_(NULL), 21 timer_id_(0) { 22 } 23 24 NPError NPObjectLifetimeTest::SetWindow(NPWindow* pNPWindow) { 25 if (pNPWindow->window == NULL) 26 return NPERR_NO_ERROR; 27 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 34 // instantiated yet. 35 timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer, 36 kNPObjectLifetimeTimerElapse, TimerProc); 37 } 38 return NPERR_NO_ERROR; 39 } 40 41 void CALLBACK NPObjectLifetimeTest::TimerProc( 42 HWND window, UINT message, UINT_PTR timer_id, 43 DWORD elapsed_milli_seconds) { 44 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"); 50 51 this_instance->timer_id_ = 0; 52 53 this_instance->other_plugin_instance_object_ = 54 NPObjectLifetimeTestInstance2::plugin_instance_object_; 55 this_instance->HostFunctions()->retainobject( 56 this_instance->other_plugin_instance_object_); 57 58 NPString script; 59 script.UTF8Characters = "javascript:DeleteSecondPluginInstance()"; 60 script.UTF8Length = static_cast<uint32_t>(strlen(script.UTF8Characters)); 61 62 this_instance->HostFunctions()->geturlnotify( 63 this_instance->id(), "javascript:DeleteSecondPluginInstance()", NULL, 64 reinterpret_cast<void*>(1)); 65 } 66 67 void NPObjectLifetimeTest::URLNotify(const char* url, NPReason reason, 68 void* data) { 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(); 80 } 81 82 NPObjectLifetimeTestInstance2::NPObjectLifetimeTestInstance2( 83 NPP id, NPNetscapeFuncs *host_functions) 84 : PluginTest(id, host_functions) { 85 } 86 87 NPObjectLifetimeTestInstance2::~NPObjectLifetimeTestInstance2() { 88 if (plugin_instance_object_) { 89 HostFunctions()->releaseobject(plugin_instance_object_); 90 plugin_instance_object_ = NULL; 91 } 92 } 93 94 NPError NPObjectLifetimeTestInstance2::SetWindow(NPWindow* pNPWindow) { 95 if (pNPWindow->window == NULL) 96 return NPERR_NO_ERROR; 97 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; 104 } 105 } 106 107 return NPERR_NO_ERROR; 108 } 109 110 111 NPObjectDeletePluginInNPN_Evaluate::NPObjectDeletePluginInNPN_Evaluate( 112 NPP id, NPNetscapeFuncs *host_functions) 113 : PluginTest(id, host_functions), 114 plugin_instance_object_(NULL), 115 timer_id_(0) { 116 g_npn_evaluate_test_instance_ = this; 117 } 118 119 NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() { 120 if (plugin_instance_object_) { 121 HostFunctions()->releaseobject(plugin_instance_object_); 122 plugin_instance_object_ = NULL; 123 } 124 } 125 126 NPError NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow* np_window) { 127 if (np_window->window == NULL) 128 return NPERR_NO_ERROR; 129 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. 136 if (!timer_id_) { 137 timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer, 138 kNPObjectLifetimeTimerElapse, TimerProc); 139 } 140 return NPERR_NO_ERROR; 141 } 142 143 void CALLBACK NPObjectDeletePluginInNPN_Evaluate::TimerProc( 144 HWND window, UINT message, UINT_PTR timer_id, 145 DWORD elapsed_milli_seconds) { 146 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, 152 &window_obj); 153 154 if (!window_obj) { 155 g_npn_evaluate_test_instance_->SetError( 156 "Failed to get NPObject for plugin instance2"); 157 g_npn_evaluate_test_instance_->SignalTestCompleted(); 158 return; 159 } 160 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()); 166 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. 172 } 173 174 } // namespace NPAPIClient 175