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 "NPJSObject.h" 28 29#if ENABLE(NETSCAPE_PLUGIN_API) 30 31#include "JSNPObject.h" 32#include "NPRuntimeObjectMap.h" 33#include "NPRuntimeUtilities.h" 34#include <JavaScriptCore/JSCInlines.h> 35#include <JavaScriptCore/JSCellInlines.h> 36#include <JavaScriptCore/JSLock.h> 37#include <JavaScriptCore/JSObject.h> 38#include <JavaScriptCore/StrongInlines.h> 39#include <WebCore/Frame.h> 40#include <WebCore/IdentifierRep.h> 41#include <wtf/text/WTFString.h> 42 43using namespace JSC; 44using namespace WebCore; 45 46namespace WebKit { 47 48NPJSObject* NPJSObject::create(VM& vm, NPRuntimeObjectMap* objectMap, JSObject* jsObject) 49{ 50 // We should never have a JSNPObject inside an NPJSObject. 51 ASSERT(!jsObject->inherits(JSNPObject::info())); 52 53 NPJSObject* npJSObject = toNPJSObject(createNPObject(0, npClass())); 54 npJSObject->initialize(vm, objectMap, jsObject); 55 56 return npJSObject; 57} 58 59NPJSObject::NPJSObject() 60 : m_objectMap(0) 61{ 62} 63 64NPJSObject::~NPJSObject() 65{ 66 m_objectMap->npJSObjectDestroyed(this); 67} 68 69bool NPJSObject::isNPJSObject(NPObject* npObject) 70{ 71 return npObject->_class == npClass(); 72} 73 74void NPJSObject::initialize(VM& vm, NPRuntimeObjectMap* objectMap, JSObject* jsObject) 75{ 76 ASSERT(!m_objectMap); 77 ASSERT(!m_jsObject); 78 79 m_objectMap = objectMap; 80 m_jsObject.set(vm, jsObject); 81} 82 83static Identifier identifierFromIdentifierRep(ExecState* exec, IdentifierRep* identifierRep) 84{ 85 ASSERT(identifierRep->isString()); 86 87 const char* string = identifierRep->string(); 88 int length = strlen(string); 89 90 return Identifier(exec, String::fromUTF8WithLatin1Fallback(string, length).impl()); 91} 92 93bool NPJSObject::hasMethod(NPIdentifier methodName) 94{ 95 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName); 96 97 if (!identifierRep->isString()) 98 return false; 99 100 ExecState* exec = m_objectMap->globalExec(); 101 if (!exec) 102 return false; 103 104 JSLockHolder lock(exec); 105 106 JSValue value = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep)); 107 exec->clearException(); 108 109 CallData callData; 110 return getCallData(value, callData) != CallTypeNone; 111} 112 113bool NPJSObject::invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 114{ 115 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName); 116 117 if (!identifierRep->isString()) 118 return false; 119 120 ExecState* exec = m_objectMap->globalExec(); 121 if (!exec) 122 return false; 123 124 JSLockHolder lock(exec); 125 126 JSValue function = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep)); 127 return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result); 128} 129 130bool NPJSObject::invokeDefault(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 131{ 132 ExecState* exec = m_objectMap->globalExec(); 133 if (!exec) 134 return false; 135 136 JSLockHolder lock(exec); 137 138 JSValue function = m_jsObject.get(); 139 return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result); 140} 141 142bool NPJSObject::hasProperty(NPIdentifier identifier) 143{ 144 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(identifier); 145 146 ExecState* exec = m_objectMap->globalExec(); 147 if (!exec) 148 return false; 149 150 JSLockHolder lock(exec); 151 152 bool result; 153 if (identifierRep->isString()) 154 result = m_jsObject->hasProperty(exec, identifierFromIdentifierRep(exec, identifierRep)); 155 else 156 result = m_jsObject->hasProperty(exec, identifierRep->number()); 157 158 exec->clearException(); 159 return result; 160} 161 162bool NPJSObject::getProperty(NPIdentifier propertyName, NPVariant* result) 163{ 164 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName); 165 166 ExecState* exec = m_objectMap->globalExec(); 167 if (!exec) 168 return false; 169 170 JSLockHolder lock(exec); 171 JSValue jsResult; 172 if (identifierRep->isString()) 173 jsResult = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep)); 174 else 175 jsResult = m_jsObject->get(exec, identifierRep->number()); 176 177 m_objectMap->convertJSValueToNPVariant(exec, jsResult, *result); 178 exec->clearException(); 179 return true; 180} 181 182bool NPJSObject::setProperty(NPIdentifier propertyName, const NPVariant* value) 183{ 184 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName); 185 186 ExecState* exec = m_objectMap->globalExec(); 187 if (!exec) 188 return false; 189 190 JSLockHolder lock(exec); 191 192 JSValue jsValue = m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), *value); 193 if (identifierRep->isString()) { 194 PutPropertySlot slot(m_jsObject.get()); 195 m_jsObject->methodTable()->put(m_jsObject.get(), exec, identifierFromIdentifierRep(exec, identifierRep), jsValue, slot); 196 } else 197 m_jsObject->methodTable()->putByIndex(m_jsObject.get(), exec, identifierRep->number(), jsValue, false); 198 exec->clearException(); 199 200 return true; 201} 202 203bool NPJSObject::removeProperty(NPIdentifier propertyName) 204{ 205 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName); 206 207 ExecState* exec = m_objectMap->globalExec(); 208 if (!exec) 209 return false; 210 211 JSLockHolder lock(exec); 212 if (identifierRep->isString()) { 213 Identifier identifier = identifierFromIdentifierRep(exec, identifierRep); 214 215 if (!m_jsObject->hasProperty(exec, identifier)) { 216 exec->clearException(); 217 return false; 218 } 219 220 m_jsObject->methodTable()->deleteProperty(m_jsObject.get(), exec, identifier); 221 } else { 222 if (!m_jsObject->hasProperty(exec, identifierRep->number())) { 223 exec->clearException(); 224 return false; 225 } 226 227 m_jsObject->methodTable()->deletePropertyByIndex(m_jsObject.get(), exec, identifierRep->number()); 228 } 229 230 exec->clearException(); 231 return true; 232} 233 234bool NPJSObject::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount) 235{ 236 ExecState* exec = m_objectMap->globalExec(); 237 if (!exec) 238 return false; 239 240 JSLockHolder lock(exec); 241 242 PropertyNameArray propertyNames(exec); 243 m_jsObject->methodTable()->getPropertyNames(m_jsObject.get(), exec, propertyNames, ExcludeDontEnumProperties); 244 245 NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(propertyNames.size()); 246 247 for (size_t i = 0; i < propertyNames.size(); ++i) 248 nameIdentifiers[i] = static_cast<NPIdentifier>(IdentifierRep::get(propertyNames[i].string().utf8().data())); 249 250 *identifiers = nameIdentifiers; 251 *identifierCount = propertyNames.size(); 252 253 return true; 254} 255 256bool NPJSObject::construct(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 257{ 258 ExecState* exec = m_objectMap->globalExec(); 259 if (!exec) 260 return false; 261 262 JSLockHolder lock(exec); 263 264 ConstructData constructData; 265 ConstructType constructType = getConstructData(m_jsObject.get(), constructData); 266 if (constructType == ConstructTypeNone) 267 return false; 268 269 // Convert the passed in arguments. 270 MarkedArgumentBuffer argumentList; 271 for (uint32_t i = 0; i < argumentCount; ++i) 272 argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), arguments[i])); 273 274 JSValue value = JSC::construct(exec, m_jsObject.get(), constructType, constructData, argumentList); 275 276 // Convert and return the new object. 277 m_objectMap->convertJSValueToNPVariant(exec, value, *result); 278 exec->clearException(); 279 280 return true; 281} 282 283bool NPJSObject::invoke(ExecState* exec, JSGlobalObject* globalObject, JSValue function, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 284{ 285 CallData callData; 286 CallType callType = getCallData(function, callData); 287 if (callType == CallTypeNone) 288 return false; 289 290 // Convert the passed in arguments. 291 MarkedArgumentBuffer argumentList; 292 for (uint32_t i = 0; i < argumentCount; ++i) 293 argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, globalObject, arguments[i])); 294 295 JSValue value = JSC::call(exec, function, callType, callData, m_jsObject.get(), argumentList); 296 297 // Convert and return the result of the function call. 298 m_objectMap->convertJSValueToNPVariant(exec, value, *result); 299 exec->clearException(); 300 301 return true; 302} 303 304NPClass* NPJSObject::npClass() 305{ 306 static NPClass npClass = { 307 NP_CLASS_STRUCT_VERSION, 308 NP_Allocate, 309 NP_Deallocate, 310 0, 311 NP_HasMethod, 312 NP_Invoke, 313 NP_InvokeDefault, 314 NP_HasProperty, 315 NP_GetProperty, 316 NP_SetProperty, 317 NP_RemoveProperty, 318 NP_Enumerate, 319 NP_Construct 320 }; 321 322 return &npClass; 323} 324 325NPObject* NPJSObject::NP_Allocate(NPP npp, NPClass*) 326{ 327 ASSERT_UNUSED(npp, !npp); 328 329 return new NPJSObject; 330} 331 332void NPJSObject::NP_Deallocate(NPObject* npObject) 333{ 334 NPJSObject* npJSObject = toNPJSObject(npObject); 335 delete npJSObject; 336} 337 338bool NPJSObject::NP_HasMethod(NPObject* npObject, NPIdentifier methodName) 339{ 340 return toNPJSObject(npObject)->hasMethod(methodName); 341} 342 343bool NPJSObject::NP_Invoke(NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 344{ 345 return toNPJSObject(npObject)->invoke(methodName, arguments, argumentCount, result); 346} 347 348bool NPJSObject::NP_InvokeDefault(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 349{ 350 return toNPJSObject(npObject)->invokeDefault(arguments, argumentCount, result); 351} 352 353bool NPJSObject::NP_HasProperty(NPObject* npObject, NPIdentifier propertyName) 354{ 355 return toNPJSObject(npObject)->hasProperty(propertyName); 356} 357 358bool NPJSObject::NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result) 359{ 360 return toNPJSObject(npObject)->getProperty(propertyName, result); 361} 362 363bool NPJSObject::NP_SetProperty(NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) 364{ 365 return toNPJSObject(npObject)->setProperty(propertyName, value); 366} 367 368bool NPJSObject::NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName) 369{ 370 return toNPJSObject(npObject)->removeProperty(propertyName); 371} 372 373bool NPJSObject::NP_Enumerate(NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount) 374{ 375 return toNPJSObject(npObject)->enumerate(identifiers, identifierCount); 376} 377 378bool NPJSObject::NP_Construct(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 379{ 380 return toNPJSObject(npObject)->construct(arguments, argumentCount, result); 381} 382 383} // namespace WebKit 384 385#endif // ENABLE(NETSCAPE_PLUGIN_API) 386