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