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 40 using namespace JSC; 41 using namespace WebCore; 42 43 namespace WebKit { 44 45 NPJSObject* 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 56 NPJSObject::NPJSObject() 57 : m_objectMap(0) 58 { 59 } 60 61 NPJSObject::~NPJSObject() 62 { 63 m_objectMap->npJSObjectDestroyed(this); 64 } 65 66 bool NPJSObject::isNPJSObject(NPObject* npObject) 67 { 68 return npObject->_class == npClass(); 69 } 70 71 void 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 80 static 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 90 bool 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 110 bool 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 127 bool 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 139 bool 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 159 bool 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 179 bool 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 200 bool 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 231 bool 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 253 bool 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 282 bool 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 305 NPClass* 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 326 NPObject* NPJSObject::NP_Allocate(NPP npp, NPClass*) 327 { 328 ASSERT_UNUSED(npp, !npp); 329 330 return new NPJSObject; 331 } 332 333 void NPJSObject::NP_Deallocate(NPObject* npObject) 334 { 335 NPJSObject* npJSObject = toNPJSObject(npObject); 336 delete npJSObject; 337 } 338 339 bool NPJSObject::NP_HasMethod(NPObject* npObject, NPIdentifier methodName) 340 { 341 return toNPJSObject(npObject)->hasMethod(methodName); 342 } 343 344 bool 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 349 bool NPJSObject::NP_InvokeDefault(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 350 { 351 return toNPJSObject(npObject)->invokeDefault(arguments, argumentCount, result); 352 } 353 354 bool NPJSObject::NP_HasProperty(NPObject* npObject, NPIdentifier propertyName) 355 { 356 return toNPJSObject(npObject)->hasProperty(propertyName); 357 } 358 359 bool NPJSObject::NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result) 360 { 361 return toNPJSObject(npObject)->getProperty(propertyName, result); 362 } 363 364 bool NPJSObject::NP_SetProperty(NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) 365 { 366 return toNPJSObject(npObject)->setProperty(propertyName, value); 367 } 368 369 bool NPJSObject::NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName) 370 { 371 return toNPJSObject(npObject)->removeProperty(propertyName); 372 } 373 374 bool NPJSObject::NP_Enumerate(NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount) 375 { 376 return toNPJSObject(npObject)->enumerate(identifiers, identifierCount); 377 } 378 379 bool 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