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