NPJSObject.cpp revision 65f03d4f644ce73618e5f4f50dd694b26f55ae12
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 "NPJSObject.h" 27 28#include "JSNPObject.h" 29#include "NPRuntimeObjectMap.h" 30#include "NPRuntimeUtilities.h" 31#include "NotImplemented.h" 32#include "PluginView.h" 33#include <JavaScriptCore/JSLock.h> 34#include <JavaScriptCore/JSObject.h> 35#include <WebCore/Frame.h> 36#include <WebCore/IdentifierRep.h> 37#include <wtf/text/WTFString.h> 38 39using namespace JSC; 40using namespace WebCore; 41 42namespace WebKit { 43 44NPJSObject* NPJSObject::create(NPRuntimeObjectMap* objectMap, JSObject* jsObject) 45{ 46 // We should never have a JSNPObject inside an NPJSObject. 47 ASSERT(!jsObject->inherits(&JSNPObject::s_info)); 48 49 NPJSObject* npJSObject = toNPJSObject(createNPObject(0, npClass())); 50 npJSObject->initialize(objectMap, jsObject); 51 52 return npJSObject; 53} 54 55NPJSObject::NPJSObject() 56 : m_objectMap(0) 57{ 58} 59 60NPJSObject::~NPJSObject() 61{ 62 m_objectMap->npJSObjectDestroyed(this); 63} 64 65bool NPJSObject::isNPJSObject(NPObject* npObject) 66{ 67 return npObject->_class == npClass(); 68} 69 70void NPJSObject::initialize(NPRuntimeObjectMap* objectMap, JSObject* jsObject) 71{ 72 ASSERT(!m_objectMap); 73 ASSERT(!m_jsObject); 74 75 m_objectMap = objectMap; 76 m_jsObject = jsObject; 77} 78 79static Identifier identifierFromIdentifierRep(ExecState* exec, IdentifierRep* identifierRep) 80{ 81 ASSERT(identifierRep->isString()); 82 83 const char* string = identifierRep->string(); 84 int length = strlen(string); 85 86 return Identifier(exec, String::fromUTF8WithLatin1Fallback(string, length).impl()); 87} 88 89bool NPJSObject::hasMethod(NPIdentifier methodName) 90{ 91 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName); 92 93 if (!identifierRep->isString()) 94 return false; 95 96 ExecState* exec = m_objectMap->globalExec(); 97 if (!exec) 98 return false; 99 100 JSLock lock(SilenceAssertionsOnly); 101 102 JSValue value = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep)); 103 exec->clearException(); 104 105 CallData callData; 106 return getCallData(value, callData) != CallTypeNone; 107} 108 109bool NPJSObject::invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 110{ 111 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName); 112 113 if (!identifierRep->isString()) 114 return false; 115 116 ExecState* exec = m_objectMap->globalExec(); 117 if (!exec) 118 return false; 119 120 JSLock lock(SilenceAssertionsOnly); 121 122 JSValue function = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep)); 123 return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result); 124} 125 126bool NPJSObject::invokeDefault(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 127{ 128 ExecState* exec = m_objectMap->globalExec(); 129 if (!exec) 130 return false; 131 132 JSLock lock(SilenceAssertionsOnly); 133 134 JSValue function = m_jsObject; 135 return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result); 136} 137 138bool NPJSObject::hasProperty(NPIdentifier identifier) 139{ 140 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(identifier); 141 142 ExecState* exec = m_objectMap->globalExec(); 143 if (!exec) 144 return false; 145 146 JSLock lock(SilenceAssertionsOnly); 147 148 bool result; 149 if (identifierRep->isString()) 150 result = m_jsObject->hasProperty(exec, identifierFromIdentifierRep(exec, identifierRep)); 151 else 152 result = m_jsObject->hasProperty(exec, identifierRep->number()); 153 154 exec->clearException(); 155 return result; 156} 157 158bool NPJSObject::getProperty(NPIdentifier propertyName, NPVariant* result) 159{ 160 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName); 161 162 ExecState* exec = m_objectMap->globalExec(); 163 if (!exec) 164 return false; 165 166 JSLock lock(SilenceAssertionsOnly); 167 JSValue jsResult; 168 if (identifierRep->isString()) 169 jsResult = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep)); 170 else 171 jsResult = m_jsObject->get(exec, identifierRep->number()); 172 173 m_objectMap->convertJSValueToNPVariant(exec, jsResult, *result); 174 exec->clearException(); 175 return true; 176} 177 178bool NPJSObject::setProperty(NPIdentifier propertyName, const NPVariant* value) 179{ 180 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName); 181 182 ExecState* exec = m_objectMap->globalExec(); 183 if (!exec) 184 return false; 185 186 JSLock lock(SilenceAssertionsOnly); 187 188 JSValue jsValue = m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), *value); 189 if (identifierRep->isString()) { 190 PutPropertySlot slot; 191 m_jsObject->put(exec, identifierFromIdentifierRep(exec, identifierRep), jsValue, slot); 192 } else 193 m_jsObject->put(exec, identifierRep->number(), jsValue); 194 exec->clearException(); 195 196 return true; 197} 198 199bool NPJSObject::removeProperty(NPIdentifier propertyName) 200{ 201 IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName); 202 203 ExecState* exec = m_objectMap->globalExec(); 204 if (!exec) 205 return false; 206 207 JSLock lock(SilenceAssertionsOnly); 208 if (identifierRep->isString()) { 209 Identifier identifier = identifierFromIdentifierRep(exec, identifierRep); 210 211 if (!m_jsObject->hasProperty(exec, identifier)) { 212 exec->clearException(); 213 return false; 214 } 215 216 m_jsObject->deleteProperty(exec, identifier); 217 } else { 218 if (!m_jsObject->hasProperty(exec, identifierRep->number())) { 219 exec->clearException(); 220 return false; 221 } 222 223 m_jsObject->deleteProperty(exec, identifierRep->number()); 224 } 225 226 exec->clearException(); 227 return true; 228} 229 230bool NPJSObject::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount) 231{ 232 ExecState* exec = m_objectMap->globalExec(); 233 if (!exec) 234 return false; 235 236 JSLock lock(SilenceAssertionsOnly); 237 238 PropertyNameArray propertyNames(exec); 239 m_jsObject->getPropertyNames(exec, propertyNames); 240 241 NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(propertyNames.size()); 242 243 for (size_t i = 0; i < propertyNames.size(); ++i) 244 nameIdentifiers[i] = static_cast<NPIdentifier>(IdentifierRep::get(propertyNames[i].ustring().utf8().data())); 245 246 *identifiers = nameIdentifiers; 247 *identifierCount = propertyNames.size(); 248 249 return true; 250} 251 252bool NPJSObject::construct(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 253{ 254 ExecState* exec = m_objectMap->globalExec(); 255 if (!exec) 256 return false; 257 258 JSLock lock(SilenceAssertionsOnly); 259 260 ConstructData constructData; 261 ConstructType constructType = getConstructData(m_jsObject, constructData); 262 if (constructType == ConstructTypeNone) 263 return false; 264 265 // Convert the passed in arguments. 266 MarkedArgumentBuffer argumentList; 267 for (uint32_t i = 0; i < argumentCount; ++i) 268 argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), arguments[i])); 269 270 exec->globalData().timeoutChecker.start(); 271 JSValue value = JSC::construct(exec, m_jsObject, constructType, constructData, argumentList); 272 exec->globalData().timeoutChecker.stop(); 273 274 // Convert and return the new object. 275 m_objectMap->convertJSValueToNPVariant(exec, value, *result); 276 exec->clearException(); 277 278 return true; 279} 280 281bool NPJSObject::invoke(ExecState* exec, JSGlobalObject* globalObject, JSValue function, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 282{ 283 CallData callData; 284 CallType callType = getCallData(function, callData); 285 if (callType == CallTypeNone) 286 return false; 287 288 // Convert the passed in arguments. 289 MarkedArgumentBuffer argumentList; 290 for (uint32_t i = 0; i < argumentCount; ++i) 291 argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, globalObject, arguments[i])); 292 293 exec->globalData().timeoutChecker.start(); 294 JSValue value = JSC::call(exec, function, callType, callData, m_jsObject, argumentList); 295 exec->globalData().timeoutChecker.stop(); 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