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(PLUGIN_PROCESS) 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 <WebCore/RunLoop.h> 39#include <wtf/MainThread.h> 40 41using namespace WebCore; 42 43namespace WebKit { 44 45NPObjectProxy* NPObjectProxy::create(NPRemoteObjectMap* npRemoteObjectMap, Plugin* plugin, uint64_t npObjectID) 46{ 47 NPObjectProxy* npObjectProxy = toNPObjectProxy(createNPObject(0, npClass())); 48 npObjectProxy->initialize(npRemoteObjectMap, plugin, npObjectID); 49 50 return npObjectProxy; 51} 52 53NPObjectProxy::NPObjectProxy() 54 : m_npRemoteObjectMap(0) 55 , m_plugin(0) 56 , m_npObjectID(0) 57{ 58} 59 60NPObjectProxy::~NPObjectProxy() 61{ 62 ASSERT(isMainThread()); 63 64 if (!m_npRemoteObjectMap) 65 return; 66 67 m_npRemoteObjectMap->npObjectProxyDestroyed(this); 68 m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Deallocate(), Messages::NPObjectMessageReceiver::Deallocate::Reply(), m_npObjectID); 69} 70 71bool NPObjectProxy::isNPObjectProxy(NPObject* npObject) 72{ 73 return npObject->_class == npClass(); 74} 75 76void NPObjectProxy::invalidate() 77{ 78 ASSERT(m_npRemoteObjectMap); 79 ASSERT(m_plugin); 80 81 m_npRemoteObjectMap = 0; 82 m_plugin = 0; 83} 84 85void NPObjectProxy::initialize(NPRemoteObjectMap* npRemoteObjectMap, Plugin* plugin, uint64_t npObjectID) 86{ 87 ASSERT(!m_npRemoteObjectMap); 88 ASSERT(!m_plugin); 89 ASSERT(!m_npObjectID); 90 91 ASSERT(npRemoteObjectMap); 92 ASSERT(plugin); 93 ASSERT(npObjectID); 94 95 m_npRemoteObjectMap = npRemoteObjectMap; 96 m_plugin = plugin; 97 m_npObjectID = npObjectID; 98} 99 100bool NPObjectProxy::hasMethod(NPIdentifier methodName) 101{ 102 if (!m_npRemoteObjectMap) 103 return false; 104 105 NPIdentifierData methodNameData = NPIdentifierData::fromNPIdentifier(methodName); 106 107 bool returnValue = false; 108 109 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::HasMethod(methodNameData), Messages::NPObjectMessageReceiver::HasMethod::Reply(returnValue), m_npObjectID)) 110 return false; 111 112 return returnValue; 113} 114 115bool NPObjectProxy::invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 116{ 117 if (!m_npRemoteObjectMap) 118 return false; 119 120 NPIdentifierData methodNameData = NPIdentifierData::fromNPIdentifier(methodName); 121 Vector<NPVariantData> argumentsData; 122 for (uint32_t i = 0; i < argumentCount; ++i) 123 argumentsData.append(m_npRemoteObjectMap->npVariantToNPVariantData(arguments[i], m_plugin)); 124 125 bool returnValue = false; 126 NPVariantData resultData; 127 128 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Invoke(methodNameData, argumentsData), Messages::NPObjectMessageReceiver::Invoke::Reply(returnValue, resultData), m_npObjectID)) 129 return false; 130 131 if (!returnValue) 132 return false; 133 134 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin); 135 return true; 136} 137 138bool NPObjectProxy::invokeDefault(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 139{ 140 if (!m_npRemoteObjectMap) 141 return false; 142 143 Vector<NPVariantData> argumentsData; 144 for (uint32_t i = 0; i < argumentCount; ++i) 145 argumentsData.append(m_npRemoteObjectMap->npVariantToNPVariantData(arguments[i], m_plugin)); 146 147 bool returnValue = false; 148 NPVariantData resultData; 149 150 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::InvokeDefault(argumentsData), Messages::NPObjectMessageReceiver::InvokeDefault::Reply(returnValue, resultData), m_npObjectID)) 151 return false; 152 153 if (!returnValue) 154 return false; 155 156 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin); 157 return true; 158} 159 160bool NPObjectProxy::hasProperty(NPIdentifier propertyName) 161{ 162 if (!m_npRemoteObjectMap) 163 return false; 164 165 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName); 166 167 bool returnValue = false; 168 169 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::HasProperty(propertyNameData), Messages::NPObjectMessageReceiver::HasProperty::Reply(returnValue), m_npObjectID)) 170 return false; 171 172 return returnValue; 173} 174 175bool NPObjectProxy::getProperty(NPIdentifier propertyName, NPVariant* result) 176{ 177 if (!m_npRemoteObjectMap) 178 return false; 179 180 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName); 181 182 bool returnValue = false; 183 NPVariantData resultData; 184 185 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::GetProperty(propertyNameData), Messages::NPObjectMessageReceiver::GetProperty::Reply(returnValue, resultData), m_npObjectID)) 186 return false; 187 188 if (!returnValue) 189 return false; 190 191 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin); 192 return true; 193} 194 195bool NPObjectProxy::setProperty(NPIdentifier propertyName, const NPVariant* value) 196{ 197 if (!m_npRemoteObjectMap) 198 return false; 199 200 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName); 201 NPVariantData propertyValueData = m_npRemoteObjectMap->npVariantToNPVariantData(*value, m_plugin); 202 203 bool returnValue = false; 204 205 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::SetProperty(propertyNameData, propertyValueData), Messages::NPObjectMessageReceiver::SetProperty::Reply(returnValue), m_npObjectID)) 206 return false; 207 208 return returnValue; 209} 210 211bool NPObjectProxy::removeProperty(NPIdentifier propertyName) 212{ 213 if (!m_npRemoteObjectMap) 214 return false; 215 216 NPIdentifierData propertyNameData = NPIdentifierData::fromNPIdentifier(propertyName); 217 218 bool returnValue = false; 219 220 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::RemoveProperty(propertyNameData), Messages::NPObjectMessageReceiver::RemoveProperty::Reply(returnValue), m_npObjectID)) 221 return false; 222 223 return returnValue; 224} 225 226bool NPObjectProxy::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount) 227{ 228 if (!m_npRemoteObjectMap) 229 return false; 230 231 bool returnValue; 232 Vector<NPIdentifierData> identifiersData; 233 234 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Enumerate(), Messages::NPObjectMessageReceiver::Enumerate::Reply(returnValue, identifiersData), m_npObjectID)) 235 return false; 236 237 if (!returnValue) 238 return false; 239 240 NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(identifiersData.size()); 241 242 for (size_t i = 0; i < identifiersData.size(); ++i) 243 nameIdentifiers[i] = identifiersData[i].createNPIdentifier(); 244 245 *identifiers = nameIdentifiers; 246 *identifierCount = identifiersData.size(); 247 return true; 248} 249 250bool NPObjectProxy::construct(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 251{ 252 if (!m_npRemoteObjectMap) 253 return false; 254 255 Vector<NPVariantData> argumentsData; 256 for (uint32_t i = 0; i < argumentCount; ++i) 257 argumentsData.append(m_npRemoteObjectMap->npVariantToNPVariantData(arguments[i], m_plugin)); 258 259 bool returnValue = false; 260 NPVariantData resultData; 261 262 if (!m_npRemoteObjectMap->connection()->sendSync(Messages::NPObjectMessageReceiver::Construct(argumentsData), Messages::NPObjectMessageReceiver::Construct::Reply(returnValue, resultData), m_npObjectID)) 263 return false; 264 265 if (!returnValue) 266 return false; 267 268 *result = m_npRemoteObjectMap->npVariantDataToNPVariant(resultData, m_plugin); 269 return true; 270} 271 272NPClass* NPObjectProxy::npClass() 273{ 274 static NPClass npClass = { 275 NP_CLASS_STRUCT_VERSION, 276 NP_Allocate, 277 NP_Deallocate, 278 0, 279 NP_HasMethod, 280 NP_Invoke, 281 NP_InvokeDefault, 282 NP_HasProperty, 283 NP_GetProperty, 284 NP_SetProperty, 285 NP_RemoveProperty, 286 NP_Enumerate, 287 NP_Construct 288 }; 289 290 return &npClass; 291} 292 293NPObject* NPObjectProxy::NP_Allocate(NPP npp, NPClass*) 294{ 295 ASSERT_UNUSED(npp, !npp); 296 297 return new NPObjectProxy; 298} 299 300void NPObjectProxy::NP_Deallocate(NPObject* npObject) 301{ 302 // http://webkit.org/b/118535 - The Java Netscape Plug-in has a background thread do some of their NPP_Destroy work. 303 // That background thread can call NP_Deallocate, and this leads to a WebProcess <-> PluginProcess deadlock. 304 // Since NPAPI behavior on a background thread is undefined, it is okay to limit this workaround to the one API 305 // that is known to be misused during plugin teardown, and to not be concerned about change in behavior if this 306 // occured at any other time. 307 if (!isMainThread()) { 308 RunLoop::main()->dispatch(bind(&NPObjectProxy::NP_Deallocate, npObject)); 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(PLUGIN_PROCESS) 364