1 /* 2 * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) 2007, 2008, 2009 Google, Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 29 #include "bindings/v8/NPV8Object.h" 30 31 #include "bindings/v8/ScriptController.h" 32 #include "bindings/v8/ScriptSourceCode.h" 33 #include "bindings/v8/V8Binding.h" 34 #include "bindings/v8/V8GCController.h" 35 #include "bindings/v8/V8NPUtils.h" 36 #include "bindings/v8/V8ObjectConstructor.h" 37 #include "bindings/v8/V8ScriptRunner.h" 38 #include "bindings/v8/WrapperTypeInfo.h" 39 #include "bindings/v8/npruntime_impl.h" 40 #include "bindings/v8/npruntime_priv.h" 41 #include "core/dom/UserGestureIndicator.h" 42 #include "core/page/DOMWindow.h" 43 #include "core/page/Frame.h" 44 #include "wtf/OwnArrayPtr.h" 45 46 #include <stdio.h> 47 #include "wtf/StringExtras.h" 48 #include "wtf/text/WTFString.h" 49 50 using namespace WebCore; 51 52 namespace WebCore { 53 54 WrapperTypeInfo* npObjectTypeInfo() 55 { 56 static WrapperTypeInfo typeInfo = { 0, 0, 0, 0, 0, 0, 0, WrapperTypeObjectPrototype }; 57 return &typeInfo; 58 } 59 60 // FIXME: Comments on why use malloc and free. 61 static NPObject* allocV8NPObject(NPP, NPClass*) 62 { 63 return static_cast<NPObject*>(malloc(sizeof(V8NPObject))); 64 } 65 66 static void freeV8NPObject(NPObject* npObject) 67 { 68 V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); 69 disposeUnderlyingV8Object(npObject); 70 free(v8NpObject); 71 } 72 73 static NPClass V8NPObjectClass = { 74 NP_CLASS_STRUCT_VERSION, 75 allocV8NPObject, 76 freeV8NPObject, 77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 78 }; 79 80 static v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject) 81 { 82 ASSERT(npObject->_class == &V8NPObjectClass); 83 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); 84 DOMWindow* window = object->rootObject; 85 if (!window || !window->isCurrentlyDisplayedInFrame()) 86 return v8::Local<v8::Context>(); 87 return ScriptController::mainWorldContext(object->rootObject->frame()); 88 } 89 90 static PassOwnArrayPtr<v8::Handle<v8::Value> > createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner, v8::Isolate* isolate) 91 { 92 OwnArrayPtr<v8::Handle<v8::Value> > argv = adoptArrayPtr(new v8::Handle<v8::Value>[argumentCount]); 93 for (uint32_t index = 0; index < argumentCount; index++) { 94 const NPVariant* arg = &arguments[index]; 95 argv[index] = convertNPVariantToV8Object(arg, owner, isolate); 96 } 97 return argv.release(); 98 } 99 100 // Create an identifier (null terminated utf8 char*) from the NPIdentifier. 101 static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name) 102 { 103 PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name); 104 if (identifier->isString) 105 return v8::String::NewSymbol(static_cast<const char*>(identifier->value.string)); 106 107 char buffer[32]; 108 snprintf(buffer, sizeof(buffer), "%d", identifier->value.number); 109 return v8::String::NewSymbol(buffer); 110 } 111 112 NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object) 113 { 114 return reinterpret_cast<NPObject*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); 115 } 116 117 NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root) 118 { 119 // Check to see if this object is already wrapped. 120 if (object->InternalFieldCount() == npObjectInternalFieldCount) { 121 WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); 122 if (typeInfo == npObjectTypeInfo()) { 123 NPObject* returnValue = v8ObjectToNPObject(object); 124 _NPN_RetainObject(returnValue); 125 return returnValue; 126 } 127 } 128 129 V8NPObjectVector* objectVector = 0; 130 if (V8PerContextData* perContextData = V8PerContextData::from(object->CreationContext())) { 131 int v8ObjectHash = object->GetIdentityHash(); 132 ASSERT(v8ObjectHash); 133 V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap(); 134 V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash); 135 if (iter != v8NPObjectMap->end()) { 136 V8NPObjectVector& objects = iter->value; 137 for (size_t index = 0; index < objects.size(); ++index) { 138 V8NPObject* v8npObject = objects.at(index); 139 if (v8npObject->v8Object == object && v8npObject->rootObject == root) { 140 _NPN_RetainObject(&v8npObject->object); 141 return reinterpret_cast<NPObject*>(v8npObject); 142 } 143 } 144 } else { 145 iter = v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).iterator; 146 } 147 objectVector = &iter->value; 148 } 149 150 V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); 151 // This is uninitialized memory, we need to clear it so that 152 // Persistent::Reset won't try to Dispose anything bogus. 153 v8npObject->v8Object.Clear(); 154 v8npObject->v8Object.Reset(v8::Isolate::GetCurrent(), object); 155 v8npObject->rootObject = root; 156 157 if (objectVector) 158 objectVector->append(v8npObject); 159 160 return reinterpret_cast<NPObject*>(v8npObject); 161 } 162 163 V8NPObject* npObjectToV8NPObject(NPObject* npObject) 164 { 165 if (npObject->_class != &V8NPObjectClass) 166 return 0; 167 V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); 168 if (v8NpObject->v8Object.IsEmpty()) 169 return 0; 170 return v8NpObject; 171 } 172 173 void disposeUnderlyingV8Object(NPObject* npObject) 174 { 175 ASSERT(npObject); 176 V8NPObject* v8NpObject = npObjectToV8NPObject(npObject); 177 if (!v8NpObject) 178 return; 179 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 180 v8::HandleScope scope(isolate); 181 v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object); 182 ASSERT(!v8Object->CreationContext().IsEmpty()); 183 if (V8PerContextData* perContextData = V8PerContextData::from(v8Object->CreationContext())) { 184 V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap(); 185 int v8ObjectHash = v8Object->GetIdentityHash(); 186 ASSERT(v8ObjectHash); 187 V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash); 188 if (iter != v8NPObjectMap->end()) { 189 V8NPObjectVector& objects = iter->value; 190 for (size_t index = 0; index < objects.size(); ++index) { 191 if (objects.at(index) == v8NpObject) { 192 objects.remove(index); 193 break; 194 } 195 } 196 if (objects.isEmpty()) 197 v8NPObjectMap->remove(v8ObjectHash); 198 } 199 } 200 v8NpObject->v8Object.Dispose(); 201 v8NpObject->v8Object.Clear(); 202 v8NpObject->rootObject = 0; 203 } 204 205 } // namespace WebCore 206 207 bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 208 { 209 if (!npObject) 210 return false; 211 212 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 213 214 V8NPObject* v8NpObject = npObjectToV8NPObject(npObject); 215 if (!v8NpObject) { 216 if (npObject->_class->invoke) 217 return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result); 218 219 VOID_TO_NPVARIANT(*result); 220 return true; 221 } 222 223 PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName); 224 if (!identifier->isString) 225 return false; 226 227 if (!strcmp(identifier->value.string, "eval")) { 228 if (argumentCount != 1) 229 return false; 230 if (arguments[0].type != NPVariantType_String) 231 return false; 232 return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); 233 } 234 235 v8::HandleScope handleScope(isolate); 236 // FIXME: should use the plugin's owner frame as the security context. 237 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 238 if (context.IsEmpty()) 239 return false; 240 241 v8::Context::Scope scope(context); 242 ExceptionCatcher exceptionCatcher; 243 244 v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object); 245 v8::Handle<v8::Value> functionObject = v8Object->Get(v8::String::NewSymbol(identifier->value.string)); 246 if (functionObject.IsEmpty() || functionObject->IsNull()) { 247 NULL_TO_NPVARIANT(*result); 248 return false; 249 } 250 if (functionObject->IsUndefined()) { 251 VOID_TO_NPVARIANT(*result); 252 return false; 253 } 254 255 Frame* frame = v8NpObject->rootObject->frame(); 256 ASSERT(frame); 257 258 // Call the function object. 259 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject); 260 OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); 261 v8::Local<v8::Value> resultObject = frame->script()->callFunction(function, v8Object, argumentCount, argv.get()); 262 263 // If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was 264 // successfully invoked". If we get an error return value, was that successfully invoked? 265 if (resultObject.IsEmpty()) 266 return false; 267 268 convertV8ObjectToNPVariant(resultObject, npObject, result); 269 return true; 270 } 271 272 // FIXME: Fix it same as _NPN_Invoke (HandleScope and such). 273 bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 274 { 275 if (!npObject) 276 return false; 277 278 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 279 280 V8NPObject* v8NpObject = npObjectToV8NPObject(npObject); 281 if (!v8NpObject) { 282 if (npObject->_class->invokeDefault) 283 return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result); 284 285 VOID_TO_NPVARIANT(*result); 286 return true; 287 } 288 289 VOID_TO_NPVARIANT(*result); 290 291 v8::HandleScope handleScope(isolate); 292 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 293 if (context.IsEmpty()) 294 return false; 295 296 v8::Context::Scope scope(context); 297 ExceptionCatcher exceptionCatcher; 298 299 // Lookup the function object and call it. 300 v8::Local<v8::Object> functionObject = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object); 301 if (!functionObject->IsFunction()) 302 return false; 303 304 v8::Local<v8::Value> resultObject; 305 v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(functionObject); 306 if (!function->IsNull()) { 307 Frame* frame = v8NpObject->rootObject->frame(); 308 ASSERT(frame); 309 310 OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); 311 resultObject = frame->script()->callFunction(function, functionObject, argumentCount, argv.get()); 312 } 313 // If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was 314 // successfully invoked". If we get an error return value, was that successfully invoked? 315 if (resultObject.IsEmpty()) 316 return false; 317 318 convertV8ObjectToNPVariant(resultObject, npObject, result); 319 return true; 320 } 321 322 bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result) 323 { 324 // FIXME: Give the embedder a way to control this. 325 bool popupsAllowed = false; 326 return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result); 327 } 328 329 bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result) 330 { 331 VOID_TO_NPVARIANT(*result); 332 if (!npObject) 333 return false; 334 335 V8NPObject* v8NpObject = npObjectToV8NPObject(npObject); 336 if (!v8NpObject) 337 return false; 338 339 v8::HandleScope handleScope; 340 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 341 if (context.IsEmpty()) 342 return false; 343 344 v8::Context::Scope scope(context); 345 ExceptionCatcher exceptionCatcher; 346 347 // FIXME: Is this branch still needed after switching to using UserGestureIndicator? 348 String filename; 349 if (!popupsAllowed) 350 filename = "npscript"; 351 352 Frame* frame = v8NpObject->rootObject->frame(); 353 ASSERT(frame); 354 355 String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); 356 357 UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture); 358 v8::Local<v8::Value> v8result = frame->script()->compileAndRunScript(ScriptSourceCode(script, KURL(ParsedURLString, filename))); 359 360 if (v8result.IsEmpty()) 361 return false; 362 363 if (_NPN_IsAlive(npObject)) 364 convertV8ObjectToNPVariant(v8result, npObject, result); 365 return true; 366 } 367 368 bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result) 369 { 370 if (!npObject) 371 return false; 372 373 if (V8NPObject* object = npObjectToV8NPObject(npObject)) { 374 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 375 v8::HandleScope handleScope(isolate); 376 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 377 if (context.IsEmpty()) 378 return false; 379 380 v8::Context::Scope scope(context); 381 ExceptionCatcher exceptionCatcher; 382 383 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); 384 v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName)); 385 386 if (v8result.IsEmpty()) 387 return false; 388 389 convertV8ObjectToNPVariant(v8result, npObject, result); 390 return true; 391 } 392 393 if (npObject->_class->hasProperty && npObject->_class->getProperty) { 394 if (npObject->_class->hasProperty(npObject, propertyName)) 395 return npObject->_class->getProperty(npObject, propertyName, result); 396 } 397 398 VOID_TO_NPVARIANT(*result); 399 return false; 400 } 401 402 bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) 403 { 404 if (!npObject) 405 return false; 406 407 if (V8NPObject* object = npObjectToV8NPObject(npObject)) { 408 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 409 v8::HandleScope handleScope(isolate); 410 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 411 if (context.IsEmpty()) 412 return false; 413 414 v8::Context::Scope scope(context); 415 ExceptionCatcher exceptionCatcher; 416 417 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); 418 obj->Set(npIdentifierToV8Identifier(propertyName), convertNPVariantToV8Object(value, object->rootObject->frame()->script()->windowScriptNPObject(), context->GetIsolate())); 419 return true; 420 } 421 422 if (npObject->_class->setProperty) 423 return npObject->_class->setProperty(npObject, propertyName, value); 424 425 return false; 426 } 427 428 bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) 429 { 430 if (!npObject) 431 return false; 432 433 V8NPObject* object = npObjectToV8NPObject(npObject); 434 if (!object) 435 return false; 436 437 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 438 v8::HandleScope handleScope(isolate); 439 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 440 if (context.IsEmpty()) 441 return false; 442 v8::Context::Scope scope(context); 443 ExceptionCatcher exceptionCatcher; 444 445 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); 446 // FIXME: Verify that setting to undefined is right. 447 obj->Set(npIdentifierToV8Identifier(propertyName), v8::Undefined()); 448 return true; 449 } 450 451 bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) 452 { 453 if (!npObject) 454 return false; 455 456 if (V8NPObject* object = npObjectToV8NPObject(npObject)) { 457 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 458 v8::HandleScope handleScope(isolate); 459 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 460 if (context.IsEmpty()) 461 return false; 462 v8::Context::Scope scope(context); 463 ExceptionCatcher exceptionCatcher; 464 465 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); 466 return obj->Has(npIdentifierToV8Identifier(propertyName)); 467 } 468 469 if (npObject->_class->hasProperty) 470 return npObject->_class->hasProperty(npObject, propertyName); 471 return false; 472 } 473 474 bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) 475 { 476 if (!npObject) 477 return false; 478 479 if (V8NPObject* object = npObjectToV8NPObject(npObject)) { 480 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 481 v8::HandleScope handleScope(isolate); 482 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 483 if (context.IsEmpty()) 484 return false; 485 v8::Context::Scope scope(context); 486 ExceptionCatcher exceptionCatcher; 487 488 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); 489 v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodName)); 490 return prop->IsFunction(); 491 } 492 493 if (npObject->_class->hasMethod) 494 return npObject->_class->hasMethod(npObject, methodName); 495 return false; 496 } 497 498 void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) 499 { 500 if (!npObject || !npObjectToV8NPObject(npObject)) { 501 // We won't be able to find a proper scope for this exception, so just throw it. 502 // This is consistent with JSC, which throws a global exception all the time. 503 throwError(v8GeneralError, message, v8::Isolate::GetCurrent()); 504 return; 505 } 506 507 v8::HandleScope handleScope; 508 v8::Handle<v8::Context> context = toV8Context(0, npObject); 509 if (context.IsEmpty()) 510 return; 511 512 v8::Context::Scope scope(context); 513 ExceptionCatcher exceptionCatcher; 514 515 throwError(v8GeneralError, message, context->GetIsolate()); 516 } 517 518 bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count) 519 { 520 if (!npObject) 521 return false; 522 523 if (V8NPObject* object = npObjectToV8NPObject(npObject)) { 524 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 525 v8::HandleScope handleScope(isolate); 526 v8::Local<v8::Context> context = toV8Context(npp, npObject); 527 if (context.IsEmpty()) 528 return false; 529 v8::Context::Scope scope(context); 530 ExceptionCatcher exceptionCatcher; 531 532 v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); 533 534 // FIXME: http://b/issue?id=1210340: Use a v8::Object::Keys() method when it exists, instead of evaluating javascript. 535 536 // FIXME: Figure out how to cache this helper function. Run a helper function that collects the properties 537 // on the object into an array. 538 const char enumeratorCode[] = 539 "(function (obj) {" 540 " var props = [];" 541 " for (var prop in obj) {" 542 " props[props.length] = prop;" 543 " }" 544 " return props;" 545 "});"; 546 v8::Handle<v8::String> source = v8::String::New(enumeratorCode); 547 v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(source, context->GetIsolate()); 548 ASSERT(!result.IsEmpty()); 549 ASSERT(result->IsFunction()); 550 v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(result); 551 v8::Handle<v8::Value> argv[] = { obj }; 552 v8::Local<v8::Value> propsObj = V8ScriptRunner::callInternalFunction(enumerator, v8::Handle<v8::Object>::Cast(result), WTF_ARRAY_LENGTH(argv), argv, context->GetIsolate()); 553 if (propsObj.IsEmpty()) 554 return false; 555 556 // Convert the results into an array of NPIdentifiers. 557 v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); 558 *count = props->Length(); 559 *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) * *count)); 560 for (uint32_t i = 0; i < *count; ++i) { 561 v8::Local<v8::Value> name = props->Get(v8::Integer::New(i, context->GetIsolate())); 562 (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name)); 563 } 564 return true; 565 } 566 567 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) 568 return npObject->_class->enumerate(npObject, identifier, count); 569 570 return false; 571 } 572 573 bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 574 { 575 if (!npObject) 576 return false; 577 578 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 579 580 if (V8NPObject* object = npObjectToV8NPObject(npObject)) { 581 v8::HandleScope handleScope(isolate); 582 v8::Handle<v8::Context> context = toV8Context(npp, npObject); 583 if (context.IsEmpty()) 584 return false; 585 v8::Context::Scope scope(context); 586 ExceptionCatcher exceptionCatcher; 587 588 // Lookup the constructor function. 589 v8::Handle<v8::Object> ctorObj = v8::Local<v8::Object>::New(isolate, object->v8Object); 590 if (!ctorObj->IsFunction()) 591 return false; 592 593 // Call the constructor. 594 v8::Local<v8::Value> resultObject; 595 v8::Handle<v8::Function> ctor = v8::Handle<v8::Function>::Cast(ctorObj); 596 if (!ctor->IsNull()) { 597 Frame* frame = object->rootObject->frame(); 598 ASSERT(frame); 599 OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); 600 resultObject = V8ObjectConstructor::newInstanceInDocument(ctor, argumentCount, argv.get(), frame ? frame->document() : 0); 601 } 602 603 if (resultObject.IsEmpty()) 604 return false; 605 606 convertV8ObjectToNPVariant(resultObject, npObject, result); 607 return true; 608 } 609 610 if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct) 611 return npObject->_class->construct(npObject, arguments, argumentCount, result); 612 613 return false; 614 } 615