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 | |
41 | namespace WebKit { |
42 | |
43 | NPObjectProxy* 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 | |
51 | NPObjectProxy::NPObjectProxy() |
52 | : m_npRemoteObjectMap(0) |
53 | , m_plugin(0) |
54 | , m_npObjectID(0) |
55 | { |
56 | } |
57 | |
58 | NPObjectProxy::~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 | |
69 | bool NPObjectProxy::isNPObjectProxy(NPObject* npObject) |
70 | { |
71 | return npObject->_class == npClass(); |
72 | } |
73 | |
74 | void NPObjectProxy::invalidate() |
75 | { |
76 | ASSERT(m_npRemoteObjectMap); |
77 | ASSERT(m_plugin); |
78 | |
79 | m_npRemoteObjectMap = 0; |
80 | m_plugin = 0; |
81 | } |
82 | |
83 | void 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 | |
98 | bool 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 | |
113 | bool 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 | |
136 | bool 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 | |
158 | bool 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 | |
173 | bool 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 | |
193 | bool 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 | |
209 | bool 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 | |
224 | bool 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 | |
248 | bool 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 | |
270 | NPClass* 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 | |
291 | NPObject* NPObjectProxy::NP_Allocate(NPP npp, NPClass*) |
292 | { |
293 | ASSERT_UNUSED(npp, !npp); |
294 | |
295 | return new NPObjectProxy; |
296 | } |
297 | |
298 | void 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 | |
316 | bool NPObjectProxy::NP_HasMethod(NPObject* npObject, NPIdentifier methodName) |
317 | { |
318 | return toNPObjectProxy(npObject)->hasMethod(methodName); |
319 | } |
320 | |
321 | bool 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 | |
326 | bool NPObjectProxy::NP_InvokeDefault(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) |
327 | { |
328 | return toNPObjectProxy(npObject)->invokeDefault(arguments, argumentCount, result); |
329 | } |
330 | |
331 | bool NPObjectProxy::NP_HasProperty(NPObject* npObject, NPIdentifier propertyName) |
332 | { |
333 | return toNPObjectProxy(npObject)->hasProperty(propertyName); |
334 | } |
335 | |
336 | bool NPObjectProxy::NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result) |
337 | { |
338 | return toNPObjectProxy(npObject)->getProperty(propertyName, result); |
339 | } |
340 | |
341 | bool NPObjectProxy::NP_SetProperty(NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) |
342 | { |
343 | return toNPObjectProxy(npObject)->setProperty(propertyName, value); |
344 | } |
345 | |
346 | bool NPObjectProxy::NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName) |
347 | { |
348 | return toNPObjectProxy(npObject)->removeProperty(propertyName); |
349 | } |
350 | |
351 | bool NPObjectProxy::NP_Enumerate(NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount) |
352 | { |
353 | return toNPObjectProxy(npObject)->enumerate(identifiers, identifierCount); |
354 | } |
355 | |
356 | bool 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 | |