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