| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. |
| 3 * Copyright (C) 2007-2009 Google, Inc. All rights reserved. | 3 * Copyright (C) 2007, 2008, 2009 Google, Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| 11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
| 13 * | 13 * |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #include "config.h" | 27 #include "config.h" |
| 28 | 28 |
| 29 #include <stdio.h> | 29 #include "NPV8Object.h" |
| 30 | 30 |
| 31 #define max max | |
| 32 #define min min | |
| 33 #include <v8.h> | |
| 34 #include "NPV8Object.h" | |
| 35 #include "ChromiumBridge.h" | 31 #include "ChromiumBridge.h" |
| 32 #include "DOMWindow.h" |
| 36 #include "Frame.h" | 33 #include "Frame.h" |
| 37 #include "bindings/npruntime.h" | 34 #include "OwnArrayPtr.h" |
| 38 #include "npruntime_priv.h" | |
| 39 #include "PlatformString.h" | 35 #include "PlatformString.h" |
| 40 #include "ScriptController.h" | 36 #include "ScriptController.h" |
| 41 #include "V8CustomBinding.h" | 37 #include "V8CustomBinding.h" |
| 42 #include "V8GCController.h" | 38 #include "V8GCController.h" |
| 43 #include "V8Helpers.h" | 39 #include "V8Helpers.h" |
| 44 #include "V8NPUtils.h" | 40 #include "V8NPUtils.h" |
| 45 #include "V8Proxy.h" | 41 #include "V8Proxy.h" |
| 46 #include "DOMWindow.h" | 42 #include "bindings/npruntime.h" |
| 43 #include "npruntime_priv.h" |
| 44 #include "wtf/StringExtras.h" |
| 45 |
| 46 #include <stdio.h> |
| 47 #include <v8.h> |
| 47 | 48 |
| 48 using WebCore::toV8Context; | 49 using WebCore::toV8Context; |
| 49 using WebCore::toV8Proxy; | 50 using WebCore::toV8Proxy; |
| 50 using WebCore::V8ClassIndex; | 51 using WebCore::V8ClassIndex; |
| 51 using WebCore::V8Custom; | 52 using WebCore::V8Custom; |
| 52 using WebCore::V8DOMWrapper; | 53 using WebCore::V8DOMWrapper; |
| 53 using WebCore::V8GCController; | 54 using WebCore::V8GCController; |
| 54 using WebCore::V8Proxy; | 55 using WebCore::V8Proxy; |
| 55 | 56 |
| 56 // FIXME(mbelshe): comments on why use malloc and free. | 57 // FIXME: Comments on why use malloc and free. |
| 57 static NPObject* AllocV8NPObject(NPP, NPClass*) | 58 static NPObject* allocV8NPObject(NPP, NPClass*) |
| 58 { | 59 { |
| 59 return static_cast<NPObject*>(malloc(sizeof(V8NPObject))); | 60 return static_cast<NPObject*>(malloc(sizeof(V8NPObject))); |
| 60 } | 61 } |
| 61 | 62 |
| 62 static void FreeV8NPObject(NPObject* npobj) | 63 static void freeV8NPObject(NPObject* npObject) |
| 63 { | 64 { |
| 64 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 65 V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); |
| 65 #ifndef NDEBUG | 66 #ifndef NDEBUG |
| 66 V8GCController::unregisterGlobalHandle(object, object->v8Object); | 67 V8GCController::unregisterGlobalHandle(v8NpObject, v8NpObject->v8Object); |
| 67 #endif | 68 #endif |
| 68 object->v8Object.Dispose(); | 69 v8NpObject->v8Object.Dispose(); |
| 69 free(object); | 70 free(v8NpObject); |
| 70 } | 71 } |
| 71 | 72 |
| 72 static v8::Handle<v8::Value>* listFromVariantArgs(const NPVariant* args, | 73 static v8::Handle<v8::Value>* createValueListFromVariantArgs(const NPVariant* ar
guments, uint32_t argumentCount, NPObject* owner) |
| 73 uint32_t argCount, | 74 { |
| 74 NPObject *owner) | 75 v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argumentCount]; |
| 75 { | 76 for (uint32_t index = 0; index < argumentCount; index++) { |
| 76 v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argCount]; | 77 const NPVariant* arg = &arguments[index]; |
| 77 for (uint32_t index = 0; index < argCount; index++) { | |
| 78 const NPVariant *arg = &args[index]; | |
| 79 argv[index] = convertNPVariantToV8Object(arg, owner); | 78 argv[index] = convertNPVariantToV8Object(arg, owner); |
| 80 } | 79 } |
| 81 return argv; | 80 return argv; |
| 82 } | 81 } |
| 83 | 82 |
| 84 // Create an identifier (null terminated utf8 char*) from the NPIdentifier. | 83 // Create an identifier (null terminated utf8 char*) from the NPIdentifier. |
| 85 static v8::Local<v8::String> NPIdentifierToV8Identifier(NPIdentifier name) | 84 static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name) |
| 86 { | 85 { |
| 87 PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name); | 86 PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name); |
| 88 if (identifier->isString) | 87 if (identifier->isString) |
| 89 return v8::String::New(static_cast<const char *>(identifier->value.strin
g)); | 88 return v8::String::New(static_cast<const char*>(identifier->value.string
)); |
| 90 | 89 |
| 91 char buf[32]; | 90 char buffer[32]; |
| 92 sprintf(buf, "%d", identifier->value.number); | 91 snprintf(buffer, sizeof(buffer), "%d", identifier->value.number); |
| 93 return v8::String::New(buf); | 92 return v8::String::New(buffer); |
| 94 } | 93 } |
| 95 | 94 |
| 96 static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, | 95 static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, |
| 97 AllocV8NPObject, | 96 allocV8NPObject, |
| 98 FreeV8NPObject, | 97 freeV8NPObject, |
| 99 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 98 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 100 | 99 |
| 101 // NPAPI's npruntime functions | 100 // NPAPI's npruntime functions. |
| 102 NPClass* npScriptObjectClass = &V8NPObjectClass; | 101 NPClass* npScriptObjectClass = &V8NPObjectClass; |
| 103 | 102 |
| 104 NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore
::DOMWindow* root) | 103 NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore
::DOMWindow* root) |
| 105 { | 104 { |
| 106 // Check to see if this object is already wrapped. | 105 // Check to see if this object is already wrapped. |
| 107 if (object->InternalFieldCount() == V8Custom::kNPObjectInternalFieldCount && | 106 if (object->InternalFieldCount() == V8Custom::kNPObjectInternalFieldCount) { |
| 108 object->GetInternalField(V8Custom::kDOMWrapperTypeIndex)->IsNumber() && | 107 v8::Local<v8::Value> typeIndex = object->GetInternalField(V8Custom::kDOM
WrapperTypeIndex); |
| 109 object->GetInternalField(V8Custom::kDOMWrapperTypeIndex)->Uint32Value()
== V8ClassIndex::NPOBJECT) { | 108 if (typeIndex->IsNumber() && typeIndex->Uint32Value() == V8ClassIndex::N
POBJECT) { |
| 110 | 109 |
| 111 NPObject* rv = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassInde
x::NPOBJECT, object); | 110 NPObject* returnValue = V8DOMWrapper::convertToNativeObject<NPObject
>(V8ClassIndex::NPOBJECT, object); |
| 112 NPN_RetainObject(rv); | 111 NPN_RetainObject(returnValue); |
| 113 return rv; | 112 return returnValue; |
| 114 } | 113 } |
| 115 | 114 } |
| 116 V8NPObject* obj = reinterpret_cast<V8NPObject*>(NPN_CreateObject(npp, &V8NPO
bjectClass)); | 115 |
| 117 obj->v8Object = v8::Persistent<v8::Object>::New(object); | 116 V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(NPN_CreateObject(npp,
&V8NPObjectClass)); |
| 117 v8npObject->v8Object = v8::Persistent<v8::Object>::New(object); |
| 118 #ifndef NDEBUG | 118 #ifndef NDEBUG |
| 119 V8GCController::registerGlobalHandle(WebCore::NPOBJECT, obj, obj->v8Object); | 119 V8GCController::registerGlobalHandle(WebCore::NPOBJECT, v8npObject, v8npObje
ct->v8Object); |
| 120 #endif | 120 #endif |
| 121 obj->rootObject = root; | 121 v8npObject->rootObject = root; |
| 122 return reinterpret_cast<NPObject*>(obj); | 122 return reinterpret_cast<NPObject*>(v8npObject); |
| 123 } | 123 } |
| 124 | 124 |
| 125 bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, | 125 bool NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVa
riant* arguments, uint32_t argumentCount, NPVariant* result) |
| 126 const NPVariant *args, uint32_t argCount, NPVariant *result) | 126 { |
| 127 { | 127 if (!npObject) |
| 128 if (!npobj) | 128 return false; |
| 129 return false; | 129 |
| 130 | 130 if (npObject->_class != npScriptObjectClass) { |
| 131 if (npobj->_class == npScriptObjectClass) { | 131 if (npObject->_class->invoke) |
| 132 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 132 return npObject->_class->invoke(npObject, methodName, arguments, arg
umentCount, result); |
| 133 | 133 |
| 134 PrivateIdentifier *identifier = static_cast<PrivateIdentifier*>(methodNa
me); | 134 VOID_TO_NPVARIANT(*result); |
| 135 if (!identifier->isString) | 135 return true; |
| 136 } |
| 137 |
| 138 V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); |
| 139 |
| 140 PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName); |
| 141 if (!identifier->isString) |
| 142 return false; |
| 143 |
| 144 v8::HandleScope handleScope; |
| 145 // FIXME: should use the plugin's owner frame as the security context. |
| 146 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 147 if (context.IsEmpty()) |
| 148 return false; |
| 149 |
| 150 v8::Context::Scope scope(context); |
| 151 |
| 152 if (methodName == NPN_GetStringIdentifier("eval")) { |
| 153 if (argumentCount != 1) |
| 136 return false; | 154 return false; |
| 137 | 155 if (arguments[0].type != NPVariantType_String) |
| 138 v8::HandleScope handleScope; | |
| 139 // FIXME: should use the plugin's owner frame as the security context | |
| 140 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | |
| 141 if (context.IsEmpty()) | |
| 142 return false; | 156 return false; |
| 143 | 157 return NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].v
alue.stringValue), result); |
| 144 v8::Context::Scope scope(context); | 158 } |
| 145 | 159 |
| 146 // Special case the "eval" method. | 160 v8::Handle<v8::Value> functionObject = v8NpObject->v8Object->Get(v8::String:
:New(identifier->value.string)); |
| 147 if (methodName == NPN_GetStringIdentifier("eval")) { | 161 if (functionObject.IsEmpty() || functionObject->IsNull()) { |
| 148 if (argCount != 1) | 162 NULL_TO_NPVARIANT(*result); |
| 149 return false; | 163 return false; |
| 150 if (args[0].type != NPVariantType_String) | 164 } |
| 151 return false; | 165 if (functionObject->IsUndefined()) { |
| 152 return NPN_Evaluate(npp, npobj, const_cast<NPString*>(&args[0].value.s
tringValue), result); | 166 VOID_TO_NPVARIANT(*result); |
| 153 } | 167 return false; |
| 154 | 168 } |
| 155 v8::Handle<v8::Value> funcObj = object->v8Object->Get(v8::String::New(id
entifier->value.string)); | 169 |
| 156 if (funcObj.IsEmpty() || funcObj->IsNull()) { | 170 V8Proxy* proxy = toV8Proxy(npObject); |
| 157 NULL_TO_NPVARIANT(*result); | 171 ASSERT(proxy); |
| 158 return false; | 172 |
| 159 } | 173 // Call the function object. |
| 160 if (funcObj->IsUndefined()) { | 174 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionO
bject); |
| 161 VOID_TO_NPVARIANT(*result); | 175 OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(argu
ments, argumentCount, npObject)); |
| 162 return false; | 176 v8::Local<v8::Value> resultObject = proxy->callFunction(function, v8NpObject
->v8Object, argumentCount, argv.get()); |
| 163 } | 177 |
| 164 | 178 // If we had an error, return false. The spec is a little unclear here, but
says "Returns true if the method was |
| 165 V8Proxy* proxy = toV8Proxy(npobj); | 179 // successfully invoked". If we get an error return value, was that success
fully invoked? |
| 166 ASSERT(proxy); // must not be null | 180 if (resultObject.IsEmpty()) |
| 167 | 181 return false; |
| 168 // FIXME: fix variable naming | 182 |
| 169 // Call the function object | 183 convertV8ObjectToNPVariant(resultObject, npObject, result); |
| 170 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(funcObj); | 184 return true; |
| 171 // Create list of args to pass to v8 | 185 } |
| 172 v8::Handle<v8::Value>* argv = listFromVariantArgs(args, argCount, npobj)
; | 186 |
| 173 v8::Local<v8::Value> resultObj = proxy->callFunction(func, object->v8Obj
ect, argCount, argv); | 187 // FIXME: Fix it same as NPN_Invoke (HandleScope and such). |
| 174 delete[] argv; | 188 bool NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments,
uint32_t argumentCount, NPVariant* result) |
| 175 | 189 { |
| 176 // If we had an error, return false. The spec is a little unclear here,
but | 190 if (!npObject) |
| 177 // says "Returns true if the method was successfully invoked". If we ge
t an | 191 return false; |
| 178 // error return value, was that successfully invoked? | 192 |
| 179 if (resultObj.IsEmpty()) | 193 if (npObject->_class != npScriptObjectClass) { |
| 180 return false; | 194 if (npObject->_class->invokeDefault) |
| 181 | 195 return npObject->_class->invokeDefault(npObject, arguments, argument
Count, result); |
| 182 // Convert the result back to an NPVariant | 196 |
| 183 convertV8ObjectToNPVariant(resultObj, npobj, result); | 197 VOID_TO_NPVARIANT(*result); |
| 184 return true; | 198 return true; |
| 185 } | 199 } |
| 186 | 200 |
| 187 if (npobj->_class->invoke) | 201 V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); |
| 188 return npobj->_class->invoke(npobj, methodName, args, argCount, result); | |
| 189 | 202 |
| 190 VOID_TO_NPVARIANT(*result); | 203 VOID_TO_NPVARIANT(*result); |
| 204 |
| 205 v8::HandleScope handleScope; |
| 206 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 207 if (context.IsEmpty()) |
| 208 return false; |
| 209 |
| 210 v8::Context::Scope scope(context); |
| 211 |
| 212 // Lookup the function object and call it. |
| 213 v8::Handle<v8::Object> functionObject(v8NpObject->v8Object); |
| 214 if (!functionObject->IsFunction()) |
| 215 return false; |
| 216 |
| 217 v8::Local<v8::Value> resultObject; |
| 218 v8::Handle<v8::Function> function(v8::Function::Cast(*functionObject)); |
| 219 if (!function->IsNull()) { |
| 220 V8Proxy* proxy = toV8Proxy(npObject); |
| 221 ASSERT(proxy); |
| 222 |
| 223 OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(
arguments, argumentCount, npObject)); |
| 224 resultObject = proxy->callFunction(function, functionObject, argumentCou
nt, argv.get()); |
| 225 } |
| 226 // If we had an error, return false. The spec is a little unclear here, but
says "Returns true if the method was |
| 227 // successfully invoked". If we get an error return value, was that success
fully invoked? |
| 228 if (resultObject.IsEmpty()) |
| 229 return false; |
| 230 |
| 231 convertV8ObjectToNPVariant(resultObject, npObject, result); |
| 191 return true; | 232 return true; |
| 192 } | 233 } |
| 193 | 234 |
| 194 // FIXME: Fix it same as NPN_Invoke (HandleScope and such) | 235 bool NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* re
sult) |
| 195 bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, | 236 { |
| 196 uint32_t argCount, NPVariant *result) | 237 bool popupsAllowed = WebCore::ChromiumBridge::popupsAllowed(npp); |
| 197 { | 238 return NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result); |
| 198 if (!npobj) | 239 } |
| 199 return false; | 240 |
| 200 | 241 bool NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStrin
g* npScript, NPVariant* result) |
| 201 if (npobj->_class == npScriptObjectClass) { | 242 { |
| 202 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | |
| 203 | |
| 204 VOID_TO_NPVARIANT(*result); | |
| 205 | |
| 206 v8::HandleScope handleScope; | |
| 207 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | |
| 208 if (context.IsEmpty()) | |
| 209 return false; | |
| 210 | |
| 211 v8::Context::Scope scope(context); | |
| 212 | |
| 213 // Lookup the function object | |
| 214 v8::Handle<v8::Object> funcObj(object->v8Object); | |
| 215 if (!funcObj->IsFunction()) | |
| 216 return false; | |
| 217 | |
| 218 // Call the function object | |
| 219 v8::Local<v8::Value> resultObj; | |
| 220 v8::Handle<v8::Function> func(v8::Function::Cast(*funcObj)); | |
| 221 if (!func->IsNull()) { | |
| 222 V8Proxy* proxy = toV8Proxy(npobj); | |
| 223 ASSERT(proxy); | |
| 224 | |
| 225 // Create list of args to pass to v8 | |
| 226 v8::Handle<v8::Value>* argv = listFromVariantArgs(args, argCount, np
obj); | |
| 227 resultObj = proxy->callFunction(func, funcObj, argCount, argv); | |
| 228 delete[] argv; | |
| 229 } | |
| 230 | |
| 231 // If we had an error, return false. The spec is a little unclear here,
but | |
| 232 // says "Returns true if the method was successfully invoked". If we ge
t an | |
| 233 // error return value, was that successfully invoked? | |
| 234 if (resultObj.IsEmpty()) | |
| 235 return false; | |
| 236 | |
| 237 // Convert the result back to an NPVariant. | |
| 238 convertV8ObjectToNPVariant(resultObj, npobj, result); | |
| 239 return true; | |
| 240 } | |
| 241 | |
| 242 if (npobj->_class->invokeDefault) | |
| 243 return npobj->_class->invokeDefault(npobj, args, argCount, result); | |
| 244 | |
| 245 VOID_TO_NPVARIANT(*result); | 243 VOID_TO_NPVARIANT(*result); |
| 246 return true; | 244 if (!npObject) |
| 247 } | 245 return false; |
| 248 | 246 |
| 249 bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *npscript, NPVariant *resul
t) | 247 if (npObject->_class != npScriptObjectClass) |
| 250 { | |
| 251 bool popupsAllowed = WebCore::ChromiumBridge::popupsAllowed(npp); | |
| 252 return NPN_EvaluateHelper(npp, popupsAllowed, npobj, npscript, result); | |
| 253 } | |
| 254 | |
| 255 bool NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npobj, NPString*
npscript, NPVariant *result) | |
| 256 { | |
| 257 VOID_TO_NPVARIANT(*result); | |
| 258 if (!npobj) | |
| 259 return false; | |
| 260 | |
| 261 if (npobj->_class != npScriptObjectClass) | |
| 262 return false; | 248 return false; |
| 263 | 249 |
| 264 v8::HandleScope handleScope; | 250 v8::HandleScope handleScope; |
| 265 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 251 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 266 if (context.IsEmpty()) | 252 if (context.IsEmpty()) |
| 267 return false; | 253 return false; |
| 268 | 254 |
| 269 V8Proxy* proxy = toV8Proxy(npobj); | 255 V8Proxy* proxy = toV8Proxy(npObject); |
| 270 ASSERT(proxy); | 256 ASSERT(proxy); |
| 271 | 257 |
| 272 v8::Context::Scope scope(context); | 258 v8::Context::Scope scope(context); |
| 273 | 259 |
| 274 WebCore::String filename; | 260 WebCore::String filename; |
| 275 if (!popupsAllowed) | 261 if (!popupsAllowed) |
| 276 filename = "npscript"; | 262 filename = "npscript"; |
| 277 | 263 |
| 278 // Convert UTF-8 stream to WebCore::String. | 264 WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters,
npScript->UTF8Length); |
| 279 WebCore::String script = WebCore::String::fromUTF8(npscript->UTF8Characters,
npscript->UTF8Length); | |
| 280 v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(sc
ript, WebCore::KURL(filename)), 0); | 265 v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(sc
ript, WebCore::KURL(filename)), 0); |
| 281 | 266 |
| 282 // If we had an error, return false. | |
| 283 if (v8result.IsEmpty()) | 267 if (v8result.IsEmpty()) |
| 284 return false; | 268 return false; |
| 285 | 269 |
| 286 convertV8ObjectToNPVariant(v8result, npobj, result); | 270 convertV8ObjectToNPVariant(v8result, npObject, result); |
| 287 return true; | 271 return true; |
| 288 } | 272 } |
| 289 | 273 |
| 290 bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVari
ant *result) | 274 bool NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPV
ariant* result) |
| 291 { | 275 { |
| 292 if (!npobj) | 276 if (!npObject) |
| 293 return false; | 277 return false; |
| 294 | 278 |
| 295 if (npobj->_class == npScriptObjectClass) { | 279 if (npObject->_class == npScriptObjectClass) { |
| 296 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 280 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 297 | 281 |
| 298 v8::HandleScope handleScope; | 282 v8::HandleScope handleScope; |
| 299 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 283 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 300 if (context.IsEmpty()) | 284 if (context.IsEmpty()) |
| 301 return false; | 285 return false; |
| 302 | 286 |
| 303 v8::Context::Scope scope(context); | 287 v8::Context::Scope scope(context); |
| 304 | 288 |
| 305 v8::Handle<v8::Object> obj(object->v8Object); | 289 v8::Handle<v8::Object> obj(object->v8Object); |
| 306 v8::Local<v8::Value> v8result = obj->Get(NPIdentifierToV8Identifier(prop
ertyName)); | 290 v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(prop
ertyName)); |
| 307 | 291 |
| 308 convertV8ObjectToNPVariant(v8result, npobj, result); | 292 convertV8ObjectToNPVariant(v8result, npObject, result); |
| 309 return true; | 293 return true; |
| 310 } | 294 } |
| 311 | 295 |
| 312 if (npobj->_class->hasProperty && npobj->_class->getProperty) { | 296 if (npObject->_class->hasProperty && npObject->_class->getProperty) { |
| 313 if (npobj->_class->hasProperty(npobj, propertyName)) | 297 if (npObject->_class->hasProperty(npObject, propertyName)) |
| 314 return npobj->_class->getProperty(npobj, propertyName, result); | 298 return npObject->_class->getProperty(npObject, propertyName, result)
; |
| 315 } | 299 } |
| 316 | 300 |
| 317 VOID_TO_NPVARIANT(*result); | 301 VOID_TO_NPVARIANT(*result); |
| 318 return false; | 302 return false; |
| 319 } | 303 } |
| 320 | 304 |
| 321 bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const
NPVariant *value) | 305 bool NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, con
st NPVariant* value) |
| 322 { | 306 { |
| 323 if (!npobj) | 307 if (!npObject) |
| 324 return false; | 308 return false; |
| 325 | 309 |
| 326 if (npobj->_class == npScriptObjectClass) { | 310 if (npObject->_class == npScriptObjectClass) { |
| 327 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 311 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 328 | 312 |
| 329 v8::HandleScope handleScope; | 313 v8::HandleScope handleScope; |
| 330 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 314 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 331 if (context.IsEmpty()) | 315 if (context.IsEmpty()) |
| 332 return false; | 316 return false; |
| 333 | 317 |
| 334 v8::Context::Scope scope(context); | 318 v8::Context::Scope scope(context); |
| 335 | 319 |
| 336 v8::Handle<v8::Object> obj(object->v8Object); | 320 v8::Handle<v8::Object> obj(object->v8Object); |
| 337 obj->Set(NPIdentifierToV8Identifier(propertyName), | 321 obj->Set(npIdentifierToV8Identifier(propertyName), |
| 338 convertNPVariantToV8Object(value, object->rootObject->frame()->
script()->windowScriptNPObject())); | 322 convertNPVariantToV8Object(value, object->rootObject->frame()->
script()->windowScriptNPObject())); |
| 339 return true; | 323 return true; |
| 340 } | 324 } |
| 341 | 325 |
| 342 if (npobj->_class->setProperty) | 326 if (npObject->_class->setProperty) |
| 343 return npobj->_class->setProperty(npobj, propertyName, value); | 327 return npObject->_class->setProperty(npObject, propertyName, value); |
| 344 | 328 |
| 345 return false; | 329 return false; |
| 346 } | 330 } |
| 347 | 331 |
| 348 bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName) | 332 bool NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) |
| 349 { | 333 { |
| 350 if (!npobj) | 334 if (!npObject) |
| 351 return false; | 335 return false; |
| 352 if (npobj->_class != npScriptObjectClass) | 336 if (npObject->_class != npScriptObjectClass) |
| 353 return false; | 337 return false; |
| 354 | 338 |
| 355 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 339 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 356 | 340 |
| 357 v8::HandleScope handleScope; | 341 v8::HandleScope handleScope; |
| 358 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 342 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 359 if (context.IsEmpty()) | 343 if (context.IsEmpty()) |
| 360 return false; | 344 return false; |
| 361 v8::Context::Scope scope(context); | 345 v8::Context::Scope scope(context); |
| 362 | 346 |
| 363 v8::Handle<v8::Object> obj(object->v8Object); | 347 v8::Handle<v8::Object> obj(object->v8Object); |
| 364 // FIXME(mbelshe) - verify that setting to undefined is right. | 348 // FIXME: Verify that setting to undefined is right. |
| 365 obj->Set(NPIdentifierToV8Identifier(propertyName), v8::Undefined()); | 349 obj->Set(npIdentifierToV8Identifier(propertyName), v8::Undefined()); |
| 366 return true; | 350 return true; |
| 367 } | 351 } |
| 368 | 352 |
| 369 bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName) | 353 bool NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) |
| 370 { | 354 { |
| 371 if (!npobj) | 355 if (!npObject) |
| 372 return false; | 356 return false; |
| 373 | 357 |
| 374 if (npobj->_class == npScriptObjectClass) { | 358 if (npObject->_class == npScriptObjectClass) { |
| 375 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 359 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 376 | 360 |
| 377 v8::HandleScope handleScope; | 361 v8::HandleScope handleScope; |
| 378 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 362 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 379 if (context.IsEmpty()) | 363 if (context.IsEmpty()) |
| 380 return false; | 364 return false; |
| 381 v8::Context::Scope scope(context); | 365 v8::Context::Scope scope(context); |
| 382 | 366 |
| 383 v8::Handle<v8::Object> obj(object->v8Object); | 367 v8::Handle<v8::Object> obj(object->v8Object); |
| 384 return obj->Has(NPIdentifierToV8Identifier(propertyName)); | 368 return obj->Has(npIdentifierToV8Identifier(propertyName)); |
| 385 } | 369 } |
| 386 | 370 |
| 387 if (npobj->_class->hasProperty) | 371 if (npObject->_class->hasProperty) |
| 388 return npobj->_class->hasProperty(npobj, propertyName); | 372 return npObject->_class->hasProperty(npObject, propertyName); |
| 389 return false; | 373 return false; |
| 390 } | 374 } |
| 391 | 375 |
| 392 bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName) | 376 bool NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) |
| 393 { | 377 { |
| 394 if (!npobj) | 378 if (!npObject) |
| 395 return false; | 379 return false; |
| 396 | 380 |
| 397 if (npobj->_class == npScriptObjectClass) { | 381 if (npObject->_class == npScriptObjectClass) { |
| 398 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 382 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 399 | 383 |
| 400 v8::HandleScope handleScope; | 384 v8::HandleScope handleScope; |
| 401 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 385 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 402 if (context.IsEmpty()) | 386 if (context.IsEmpty()) |
| 403 return false; | 387 return false; |
| 404 v8::Context::Scope scope(context); | 388 v8::Context::Scope scope(context); |
| 405 | 389 |
| 406 v8::Handle<v8::Object> obj(object->v8Object); | 390 v8::Handle<v8::Object> obj(object->v8Object); |
| 407 v8::Handle<v8::Value> prop = obj->Get(NPIdentifierToV8Identifier(methodN
ame)); | 391 v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodN
ame)); |
| 408 return prop->IsFunction(); | 392 return prop->IsFunction(); |
| 409 } | 393 } |
| 410 | 394 |
| 411 if (npobj->_class->hasMethod) | 395 if (npObject->_class->hasMethod) |
| 412 return npobj->_class->hasMethod(npobj, methodName); | 396 return npObject->_class->hasMethod(npObject, methodName); |
| 413 return false; | 397 return false; |
| 414 } | 398 } |
| 415 | 399 |
| 416 void NPN_SetException(NPObject *npobj, const NPUTF8 *message) | 400 void NPN_SetException(NPObject* npObject, const NPUTF8 *message) |
| 417 { | 401 { |
| 418 if (npobj->_class != npScriptObjectClass) | 402 if (npObject->_class != npScriptObjectClass) |
| 419 return; | 403 return; |
| 420 v8::HandleScope handleScope; | 404 v8::HandleScope handleScope; |
| 421 v8::Handle<v8::Context> context = toV8Context(0, npobj); | 405 v8::Handle<v8::Context> context = toV8Context(0, npObject); |
| 422 if (context.IsEmpty()) | 406 if (context.IsEmpty()) |
| 423 return; | 407 return; |
| 424 | 408 |
| 425 v8::Context::Scope scope(context); | 409 v8::Context::Scope scope(context); |
| 426 V8Proxy::throwError(V8Proxy::GeneralError, message); | 410 V8Proxy::throwError(V8Proxy::GeneralError, message); |
| 427 } | 411 } |
| 428 | 412 |
| 429 bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t
*count) | 413 bool NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint3
2_t* count) |
| 430 { | 414 { |
| 431 if (!npobj) | 415 if (!npObject) |
| 432 return false; | 416 return false; |
| 433 | 417 |
| 434 if (npobj->_class == npScriptObjectClass) { | 418 if (npObject->_class == npScriptObjectClass) { |
| 435 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 419 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 436 | 420 |
| 437 v8::HandleScope handleScope; | 421 v8::HandleScope handleScope; |
| 438 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 422 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 439 if (context.IsEmpty()) | 423 if (context.IsEmpty()) |
| 440 return false; | 424 return false; |
| 441 v8::Context::Scope scope(context); | 425 v8::Context::Scope scope(context); |
| 442 | 426 |
| 443 v8::Handle<v8::Object> obj(object->v8Object); | 427 v8::Handle<v8::Object> obj(object->v8Object); |
| 444 | 428 |
| 445 // FIXME(fqian): http://b/issue?id=1210340: Use a v8::Object::Keys() met
hod | 429 // FIXME: http://b/issue?id=1210340: Use a v8::Object::Keys() method whe
n it exists, instead of evaluating javascript. |
| 446 // when it exists, instead of evaluating javascript. | |
| 447 | 430 |
| 448 // FIXME(mpcomplete): figure out how to cache this helper function. | 431 // FIXME: Figure out how to cache this helper function. Run a helper fu
nction that collects the properties |
| 449 // Run a helper function that collects the properties on the object into | 432 // on the object into an array. |
| 450 // an array. | |
| 451 const char enumeratorCode[] = | 433 const char enumeratorCode[] = |
| 452 "(function (obj) {" | 434 "(function (obj) {" |
| 453 " var props = [];" | 435 " var props = [];" |
| 454 " for (var prop in obj) {" | 436 " for (var prop in obj) {" |
| 455 " props[props.length] = prop;" | 437 " props[props.length] = prop;" |
| 456 " }" | 438 " }" |
| 457 " return props;" | 439 " return props;" |
| 458 "});"; | 440 "});"; |
| 459 v8::Handle<v8::String> source = v8::String::New(enumeratorCode); | 441 v8::Handle<v8::String> source = v8::String::New(enumeratorCode); |
| 460 v8::Handle<v8::Script> script = v8::Script::Compile(source, 0); | 442 v8::Handle<v8::Script> script = v8::Script::Compile(source, 0); |
| 461 v8::Handle<v8::Value> enumeratorObj = script->Run(); | 443 v8::Handle<v8::Value> enumeratorObj = script->Run(); |
| 462 v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(enu
meratorObj); | 444 v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(enu
meratorObj); |
| 463 v8::Handle<v8::Value> argv[] = { obj }; | 445 v8::Handle<v8::Value> argv[] = { obj }; |
| 464 v8::Local<v8::Value> propsObj = enumerator->Call(v8::Handle<v8::Object>:
:Cast(enumeratorObj), ARRAYSIZE_UNSAFE(argv), argv); | 446 v8::Local<v8::Value> propsObj = enumerator->Call(v8::Handle<v8::Object>:
:Cast(enumeratorObj), ARRAYSIZE_UNSAFE(argv), argv); |
| 465 if (propsObj.IsEmpty()) | 447 if (propsObj.IsEmpty()) |
| 466 return false; | 448 return false; |
| 467 | 449 |
| 468 // Convert the results into an array of NPIdentifiers. | 450 // Convert the results into an array of NPIdentifiers. |
| 469 v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); | 451 v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); |
| 470 *count = props->Length(); | 452 *count = props->Length(); |
| 471 *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) *
*count)); | 453 *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) *
*count)); |
| 472 for (uint32_t i = 0; i < *count; ++i) { | 454 for (uint32_t i = 0; i < *count; ++i) { |
| 473 v8::Local<v8::Value> name = props->Get(v8::Integer::New(i)); | 455 v8::Local<v8::Value> name = props->Get(v8::Integer::New(i)); |
| 474 (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(n
ame)); | 456 (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(n
ame)); |
| 475 } | 457 } |
| 476 return true; | 458 return true; |
| 477 } | 459 } |
| 478 | 460 |
| 479 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) && npobj->_class->enumer
ate) | 461 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->
enumerate) |
| 480 return npobj->_class->enumerate(npobj, identifier, count); | 462 return npObject->_class->enumerate(npObject, identifier, count); |
| 481 | 463 |
| 482 return false; | 464 return false; |
| 483 } | 465 } |
| 484 | 466 |
| 485 bool NPN_Construct(NPP npp, NPObject* npobj, const NPVariant* args, uint32_t arg
Count, NPVariant* result) | 467 bool NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint
32_t argumentCount, NPVariant* result) |
| 486 { | 468 { |
| 487 if (!npobj) | 469 if (!npObject) |
| 488 return false; | 470 return false; |
| 489 | 471 |
| 490 if (npobj->_class == npScriptObjectClass) { | 472 if (npObject->_class == npScriptObjectClass) { |
| 491 V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); | 473 V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); |
| 492 | 474 |
| 493 v8::HandleScope handleScope; | 475 v8::HandleScope handleScope; |
| 494 v8::Handle<v8::Context> context = toV8Context(npp, npobj); | 476 v8::Handle<v8::Context> context = toV8Context(npp, npObject); |
| 495 if (context.IsEmpty()) | 477 if (context.IsEmpty()) |
| 496 return false; | 478 return false; |
| 497 v8::Context::Scope scope(context); | 479 v8::Context::Scope scope(context); |
| 498 | 480 |
| 499 // Lookup the constructor function. | 481 // Lookup the constructor function. |
| 500 v8::Handle<v8::Object> ctorObj(object->v8Object); | 482 v8::Handle<v8::Object> ctorObj(object->v8Object); |
| 501 if (!ctorObj->IsFunction()) | 483 if (!ctorObj->IsFunction()) |
| 502 return false; | 484 return false; |
| 503 | 485 |
| 504 // Call the constructor. | 486 // Call the constructor. |
| 505 v8::Local<v8::Value> resultObj; | 487 v8::Local<v8::Value> resultObject; |
| 506 v8::Handle<v8::Function> ctor(v8::Function::Cast(*ctorObj)); | 488 v8::Handle<v8::Function> ctor(v8::Function::Cast(*ctorObj)); |
| 507 if (!ctor->IsNull()) { | 489 if (!ctor->IsNull()) { |
| 508 V8Proxy* proxy = toV8Proxy(npobj); | 490 V8Proxy* proxy = toV8Proxy(npObject); |
| 509 ASSERT(proxy); | 491 ASSERT(proxy); |
| 510 | 492 |
| 511 // Create list of args to pass to v8. | 493 OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantA
rgs(arguments, argumentCount, npObject)); |
| 512 v8::Handle<v8::Value>* argv = listFromVariantArgs(args, argCount, np
obj); | 494 resultObject = proxy->newInstance(ctor, argumentCount, argv.get()); |
| 513 resultObj = proxy->newInstance(ctor, argCount, argv); | |
| 514 delete[] argv; | |
| 515 } | 495 } |
| 516 | 496 |
| 517 // If we had an error return false. | 497 if (resultObject.IsEmpty()) |
| 518 if (resultObj.IsEmpty()) | |
| 519 return false; | 498 return false; |
| 520 | 499 |
| 521 // Convert the result back to an NPVariant. | 500 convertV8ObjectToNPVariant(resultObject, npObject, result); |
| 522 convertV8ObjectToNPVariant(resultObj, npobj, result); | |
| 523 return true; | 501 return true; |
| 524 } | 502 } |
| 525 | 503 |
| 526 if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) && npobj->_class->constr
uct) | 504 if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->
construct) |
| 527 return npobj->_class->construct(npobj, args, argCount, result); | 505 return npObject->_class->construct(npObject, arguments, argumentCount, r
esult); |
| 528 | 506 |
| 529 return false; | 507 return false; |
| 530 } | 508 } |
| OLD | NEW |