1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "NPObjectProxy.h"
28
29#if ENABLE(NETSCAPE_PLUGIN_API)
30
31#include "ArgumentCoders.h"
32#include "Connection.h"
33#include "NPIdentifierData.h"
34#include "NPObjectMessageReceiverMessages.h"
35#include "NPRemoteObjectMap.h"
36#include "NPRuntimeUtilities.h"
37#include "NPVariantData.h"
38#include <wtf/MainThread.h>
39#include <wtf/RunLoop.h>
40
41namespace WebKit {
42
43NPObjectProxy* NPObjectProxy::create(NPRemoteObjectMap* npRemoteObjectMap, Plugin* plugin, uint64_t npObjectID)
44{
45 NPObjectProxy* npObjectProxy = toNPObjectProxy(createNPObject(0, npClass()));
46 npObjectProxy->initialize(npRemoteObjectMap, plugin, npObjectID);
47
48 return npObjectProxy;
49}
50
51NPObjectProxy::NPObjectProxy()
52 : m_npRemoteObjectMap(0)
53 , m_plugin(0)
54 , m_npObjectID(0)
55{
56}
57
58NPObjectProxy::~NPObjectProxy()
59{
60 ASSERT(RunLoop::isMain());
61
62 if (!m_npRemoteObjectMap)
63 return;
64
65 m_npRemoteObjectMap->npObjectProxyDestroyed(this);
66 m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Deallocate(), Messages::NPObjectMessageReceiver::Deallocate::Reply(), m_npObjectID);
67}
68
69bool NPObjectProxy::isNPObjectProxy(NPObject* npObject)
70{
71 return npObject->_class == npClass();
72}
73
74void NPObjectProxy::invalidate()
75{
76 ASSERT(m_npRemoteObjectMap);
77 ASSERT(m_plugin);
78
79 m_npRemoteObjectMap = 0;
80 m_plugin = 0;
81}
82
83void NPObjectProxy::initialize(NPRemoteObjectMap* npRemoteObjectMap, Plugin* plugin, uint64_t npObjectID)
84{
85 ASSERT(!m_npRemoteObjectMap);
86 ASSERT(!m_plugin);
87 ASSERT(!m_npObjectID);
88
89 ASSERT(npRemoteObjectMap);
90 ASSERT(plugin);
91 ASSERT(npObjectID);
92
93 m_npRemoteObjectMap = npRemoteObjectMap;
94 m_plugin = plugin;
95 m_npObjectID = npObjectID;
96}
97
98bool NPObjectProxy::hasMethod(NPIdentifier methodName)
99{
100 if (!m_npRemoteObjectMap)
101 return false;
102
103 NPIdentifierData methodNameData = NPIdentifierData::fromNPIdentifier(methodName);
104
105 bool returnValue = false;
106
107 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::HasMethod(methodNameData), Messages::NPObjectMessageReceiver::HasMethod::Reply(returnValue), m_npObjectID))
108 return false;
109
110 return returnValue;
111}
112
113bool NPObjectProxy::invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
114{
115 if (!m_npRemoteObjectMap)
116 return false;
117
118 NPIdentifierData methodNameData = NPIdentifierData::fromNPIdentifier(methodName);
119 Vector<NPVariantData> argumentsData;
120 for (uint32_t i = 0; i < argumentCount; ++i)
121 argumentsData.append(m_npRemoteObjectMap->npVariantToNPVariantData(arguments[i], m_plugin));
122
123 bool returnValue = false;
124 NPVariantData resultData;
125
126 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Invoke(methodNameData, argumentsData), Messages::NPObjectMessageReceiver::Invoke::Reply(returnValue, resultData), m_npObjectID))
127 return false;
128
129 if (!returnValue)
130 return false;
131
132 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin);
133 return true;
134}
135
136bool NPObjectProxy::invokeDefault(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
137{
138 if (!m_npRemoteObjectMap)
139 return false;
140
141 Vector<NPVariantData> argumentsData;
142 for (uint32_t i = 0; i < argumentCount; ++i)
143 argumentsData.append(m_npRemoteObjectMap->npVariantToNPVariantData(arguments[i], m_plugin));
144
145 bool returnValue = false;
146 NPVariantData resultData;
147
148 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::InvokeDefault(argumentsData), Messages::NPObjectMessageReceiver::InvokeDefault::Reply(returnValue, resultData), m_npObjectID))
149 return false;
150
151 if (!returnValue)
152 return false;
153
154 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin);
155 return true;
156}
157
158bool NPObjectProxy::hasProperty(NPIdentifier propertyName)
159{
160 if (!m_npRemoteObjectMap)
161 return false;
162
163 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName);
164
165 bool returnValue = false;
166
167 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::HasProperty(propertyNameData), Messages::NPObjectMessageReceiver::HasProperty::Reply(returnValue), m_npObjectID))
168 return false;
169
170 return returnValue;
171}
172
173bool NPObjectProxy::getProperty(NPIdentifier propertyName, NPVariant* result)
174{
175 if (!m_npRemoteObjectMap)
176 return false;
177
178 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName);
179
180 bool returnValue = false;
181 NPVariantData resultData;
182
183 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::GetProperty(propertyNameData), Messages::NPObjectMessageReceiver::GetProperty::Reply(returnValue, resultData), m_npObjectID))
184 return false;
185
186 if (!returnValue)
187 return false;
188
189 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin);
190 return true;
191}
192
193bool NPObjectProxy::setProperty(NPIdentifier propertyName, const NPVariant* value)
194{
195 if (!m_npRemoteObjectMap)
196 return false;
197
198 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName);
199 NPVariantData propertyValueData = m_npRemoteObjectMap->npVariantToNPVariantData(*value, m_plugin);
200
201 bool returnValue = false;
202
203 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::SetProperty(propertyNameData, propertyValueData), Messages::NPObjectMessageReceiver::SetProperty::Reply(returnValue), m_npObjectID))
204 return false;
205
206 return returnValue;
207}
208
209bool NPObjectProxy::removeProperty(NPIdentifier propertyName)
210{
211 if (!m_npRemoteObjectMap)
212 return false;
213
214 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName);
215
216 bool returnValue = false;
217
218 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::RemoveProperty(propertyNameData), Messages::NPObjectMessageReceiver::RemoveProperty::Reply(returnValue), m_npObjectID))
219 return false;
220
221 return returnValue;
222}
223
224bool NPObjectProxy::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount)
225{
226 if (!m_npRemoteObjectMap)
227 return false;
228
229 bool returnValue;
230 Vector<NPIdentifierData> identifiersData;
231
232 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Enumerate(), Messages::NPObjectMessageReceiver::Enumerate::Reply(returnValue, identifiersData), m_npObjectID))
233 return false;
234
235 if (!returnValue)
236 return false;
237
238 NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(identifiersData.size());
239
240 for (size_t i = 0; i < identifiersData.size(); ++i)
241 nameIdentifiers[i] = identifiersData[i].createNPIdentifier();
242
243 *identifiers = nameIdentifiers;
244 *identifierCount = identifiersData.size();
245 return true;
246}
247
248bool NPObjectProxy::construct(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
249{
250 if (!m_npRemoteObjectMap)
251 return false;
252
253 Vector<NPVariantData> argumentsData;
254 for (uint32_t i = 0; i < argumentCount; ++i)
255 argumentsData.append(m_npRemoteObjectMap->npVariantToNPVariantData(arguments[i], m_plugin));
256
257 bool returnValue = false;
258 NPVariantData resultData;
259
260 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Construct(argumentsData), Messages::NPObjectMessageReceiver::Construct::Reply(returnValue, resultData), m_npObjectID))
261 return false;
262
263 if (!returnValue)
264 return false;
265
266 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin);
267 return true;
268}
269
270NPClass* NPObjectProxy::npClass()
271{
272 static NPClass npClass = {
273 NP_CLASS_STRUCT_VERSION,
274 NP_Allocate,
275 NP_Deallocate,
276 0,
277 NP_HasMethod,
278 NP_Invoke,
279 NP_InvokeDefault,
280 NP_HasProperty,
281 NP_GetProperty,
282 NP_SetProperty,
283 NP_RemoveProperty,
284 NP_Enumerate,
285 NP_Construct
286 };
287
288 return &npClass;
289}
290
291NPObject* NPObjectProxy::NP_Allocate(NPP npp, NPClass*)
292{
293 ASSERT_UNUSED(npp, !npp);
294
295 return new NPObjectProxy;
296}
297
298void NPObjectProxy::NP_Deallocate(NPObject* npObject)
299{
300 // http://webkit.org/b/118535 - The Java Netscape Plug-in has a background thread do some of their NPP_Destroy work.
301 // That background thread can call NP_Deallocate, and this leads to a WebProcess <-> PluginProcess deadlock.
302 // Since NPAPI behavior on a background thread is undefined, it is okay to limit this workaround to the one API
303 // that is known to be misused during plugin teardown, and to not be concerned about change in behavior if this
304 // occured at any other time.
305 if (!RunLoop::isMain()) {
306 RunLoop::main().dispatch([npObject] {
307 NP_Deallocate(npObject);
308 });
309 return;
310 }
311
312 NPObjectProxy* npObjectProxy = toNPObjectProxy(npObject);
313 delete npObjectProxy;
314}
315
316bool NPObjectProxy::NP_HasMethod(NPObject* npObject, NPIdentifier methodName)
317{
318 return toNPObjectProxy(npObject)->hasMethod(methodName);
319}
320
321bool NPObjectProxy::NP_Invoke(NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
322{
323 return toNPObjectProxy(npObject)->invoke(methodName, arguments, argumentCount, result);
324}
325
326bool NPObjectProxy::NP_InvokeDefault(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
327{
328 return toNPObjectProxy(npObject)->invokeDefault(arguments, argumentCount, result);
329}
330
331bool NPObjectProxy::NP_HasProperty(NPObject* npObject, NPIdentifier propertyName)
332{
333 return toNPObjectProxy(npObject)->hasProperty(propertyName);
334}
335
336bool NPObjectProxy::NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
337{
338 return toNPObjectProxy(npObject)->getProperty(propertyName, result);
339}
340
341bool NPObjectProxy::NP_SetProperty(NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
342{
343 return toNPObjectProxy(npObject)->setProperty(propertyName, value);
344}
345
346bool NPObjectProxy::NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName)
347{
348 return toNPObjectProxy(npObject)->removeProperty(propertyName);
349}
350
351bool NPObjectProxy::NP_Enumerate(NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount)
352{
353 return toNPObjectProxy(npObject)->enumerate(identifiers, identifierCount);
354}
355
356bool NPObjectProxy::NP_Construct(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
357{
358 return toNPObjectProxy(npObject)->construct(arguments, argumentCount, result);
359}
360
361} // namespace WebKit
362
363#endif // ENABLE(NETSCAPE_PLUGIN_API)
364