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 (!isMainThread()) { 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