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