• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NPObjectLifetimeTest(NPP id,NPNetscapeFuncs * host_functions)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 
SetWindow(NPWindow * pNPWindow)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 
TimerProc(HWND window,UINT message,UINT_PTR timer_id,DWORD elapsed_milli_seconds)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 
URLNotify(const char * url,NPReason reason,void * data)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 
NPObjectLifetimeTestInstance2(NPP id,NPNetscapeFuncs * host_functions)82 NPObjectLifetimeTestInstance2::NPObjectLifetimeTestInstance2(
83     NPP id, NPNetscapeFuncs *host_functions)
84     : PluginTest(id, host_functions) {
85 }
86 
~NPObjectLifetimeTestInstance2()87 NPObjectLifetimeTestInstance2::~NPObjectLifetimeTestInstance2() {
88   if (plugin_instance_object_) {
89     HostFunctions()->releaseobject(plugin_instance_object_);
90     plugin_instance_object_ = NULL;
91   }
92 }
93 
SetWindow(NPWindow * pNPWindow)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 
NPObjectDeletePluginInNPN_Evaluate(NPP id,NPNetscapeFuncs * host_functions)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 
~NPObjectDeletePluginInNPN_Evaluate()119 NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() {
120   if (plugin_instance_object_) {
121     HostFunctions()->releaseobject(plugin_instance_object_);
122     plugin_instance_object_ = NULL;
123   }
124 }
125 
SetWindow(NPWindow * np_window)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 
TimerProc(HWND window,UINT message,UINT_PTR timer_id,DWORD elapsed_milli_seconds)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