Commit 2bb6803c authored by darin@chromium.org's avatar darin@chromium.org
Browse files

2010-05-20 Darin Fisher <darin@chromium.org>

        Reviewed by Nate Chapin.

        [chromium] Provide a way to catch exceptions thrown while interacting
        with a NPObject via WebBindings methods.
        https://bugs.webkit.org/show_bug.cgi?id=39378

        This change also includes a small bit of cleanup in V8NPObject and
        friends.  I moved code into the WebCore namespace where appropriate.
        
        In _NPN_Invoke, I also moved the call to _NPN_Evaluate outside of the
        context scope.  I did this to avoid having nested ExceptionCatcher
        objects, which is not strictly necessary, but it seemed cleaner.
        _NPN_Evaluate already takes care of creating a context scope.

        * bindings/v8/NPV8Object.cpp:
        (WebCore::v8ObjectToNPObject):
        (WebCore::npCreateV8ScriptObject):
        (_NPN_Invoke):
        (_NPN_InvokeDefault):
        (_NPN_Evaluate):
        (_NPN_EvaluateHelper):
        (_NPN_GetProperty):
        (_NPN_SetProperty):
        (_NPN_RemoveProperty):
        (_NPN_HasProperty):
        (_NPN_HasMethod):
        (_NPN_SetException):
        (_NPN_Enumerate):
        (_NPN_Construct):
        * bindings/v8/NPV8Object.h:
        * bindings/v8/V8NPObject.cpp:
        * bindings/v8/V8NPObject.h:
        * bindings/v8/V8NPUtils.cpp:
        (WebCore::convertV8ObjectToNPVariant):
        (WebCore::pushExceptionHandler):
        (WebCore::popExceptionHandler):
        (WebCore::ExceptionCatcher::ExceptionCatcher):
        (WebCore::ExceptionCatcher::~ExceptionCatcher):
        * bindings/v8/V8NPUtils.h:
        * bindings/v8/npruntime.cpp:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@59862 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a6d6b6cd
2010-05-20 Darin Fisher <darin@chromium.org>
Reviewed by Nate Chapin.
[chromium] Provide a way to catch exceptions thrown while interacting
with a NPObject via WebBindings methods.
https://bugs.webkit.org/show_bug.cgi?id=39378
This change also includes a small bit of cleanup in V8NPObject and
friends. I moved code into the WebCore namespace where appropriate.
In _NPN_Invoke, I also moved the call to _NPN_Evaluate outside of the
context scope. I did this to avoid having nested ExceptionCatcher
objects, which is not strictly necessary, but it seemed cleaner.
_NPN_Evaluate already takes care of creating a context scope.
* bindings/v8/NPV8Object.cpp:
(WebCore::v8ObjectToNPObject):
(WebCore::npCreateV8ScriptObject):
(_NPN_Invoke):
(_NPN_InvokeDefault):
(_NPN_Evaluate):
(_NPN_EvaluateHelper):
(_NPN_GetProperty):
(_NPN_SetProperty):
(_NPN_RemoveProperty):
(_NPN_HasProperty):
(_NPN_HasMethod):
(_NPN_SetException):
(_NPN_Enumerate):
(_NPN_Construct):
* bindings/v8/NPV8Object.h:
* bindings/v8/V8NPObject.cpp:
* bindings/v8/V8NPObject.h:
* bindings/v8/V8NPUtils.cpp:
(WebCore::convertV8ObjectToNPVariant):
(WebCore::pushExceptionHandler):
(WebCore::popExceptionHandler):
(WebCore::ExceptionCatcher::ExceptionCatcher):
(WebCore::ExceptionCatcher::~ExceptionCatcher):
* bindings/v8/V8NPUtils.h:
* bindings/v8/npruntime.cpp:
2010-05-20 Marcus Bulach <bulach@chromium.org>
 
Reviewed by Steve Block.
......@@ -52,13 +52,7 @@
#include <v8.h>
#include <wtf/StringExtras.h>
using WebCore::npObjectInternalFieldCount;
using WebCore::toV8Context;
using WebCore::toV8Proxy;
using WebCore::V8DOMWrapper;
using WebCore::V8GCController;
using WebCore::V8Proxy;
using WebCore::WrapperTypeInfo;
using namespace WebCore;
namespace WebCore {
......@@ -68,8 +62,6 @@ WrapperTypeInfo* npObjectTypeInfo()
return &typeInfo;
}
}
// FIXME: Comments on why use malloc and free.
static NPObject* allocV8NPObject(NPP, NPClass*)
{
......@@ -110,7 +102,7 @@ static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name)
NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object)
{
return reinterpret_cast<NPObject*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperObjectIndex));
return reinterpret_cast<NPObject*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
}
static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION,
......@@ -121,12 +113,12 @@ static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION,
// NPAPI's npruntime functions.
NPClass* npScriptObjectClass = &V8NPObjectClass;
NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore::DOMWindow* root)
NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root)
{
// Check to see if this object is already wrapped.
if (object->InternalFieldCount() == npObjectInternalFieldCount) {
WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperTypeIndex));
if (typeInfo == WebCore::npObjectTypeInfo()) {
WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex));
if (typeInfo == npObjectTypeInfo()) {
NPObject* returnValue = v8ObjectToNPObject(object);
_NPN_RetainObject(returnValue);
......@@ -137,12 +129,14 @@ NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore
V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass));
v8npObject->v8Object = v8::Persistent<v8::Object>::New(object);
#ifndef NDEBUG
V8GCController::registerGlobalHandle(WebCore::NPOBJECT, v8npObject, v8npObject->v8Object);
V8GCController::registerGlobalHandle(NPOBJECT, v8npObject, v8npObject->v8Object);
#endif
v8npObject->rootObject = root;
return reinterpret_cast<NPObject*>(v8npObject);
}
} // namespace WebCore
bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
if (!npObject)
......@@ -162,6 +156,14 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV
if (!identifier->isString)
return false;
if (!strcmp(identifier->value.string, "eval")) {
if (argumentCount != 1)
return false;
if (arguments[0].type != NPVariantType_String)
return false;
return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result);
}
v8::HandleScope handleScope;
// FIXME: should use the plugin's owner frame as the security context.
v8::Handle<v8::Context> context = toV8Context(npp, npObject);
......@@ -169,14 +171,7 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV
return false;
v8::Context::Scope scope(context);
if (methodName == _NPN_GetStringIdentifier("eval")) {
if (argumentCount != 1)
return false;
if (arguments[0].type != NPVariantType_String)
return false;
return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result);
}
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Value> functionObject = v8NpObject->v8Object->Get(v8::String::New(identifier->value.string));
if (functionObject.IsEmpty() || functionObject->IsNull()) {
......@@ -229,6 +224,7 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments,
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
// Lookup the function object and call it.
v8::Handle<v8::Object> functionObject(v8NpObject->v8Object);
......@@ -255,7 +251,7 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments,
bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result)
{
bool popupsAllowed = WebCore::PlatformBridge::popupsAllowed(npp);
bool popupsAllowed = PlatformBridge::popupsAllowed(npp);
return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result);
}
......@@ -277,13 +273,14 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri
ASSERT(proxy);
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
WebCore::String filename;
String filename;
if (!popupsAllowed)
filename = "npscript";
WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);
v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(WebCore::ParsedURLString, filename)), 0);
String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);
v8::Local<v8::Value> v8result = proxy->evaluate(ScriptSourceCode(script, KURL(ParsedURLString, filename)), 0);
if (v8result.IsEmpty())
return false;
......@@ -306,6 +303,7 @@ bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NP
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj(object->v8Object);
v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName));
......@@ -340,6 +338,7 @@ bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, co
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj(object->v8Object);
obj->Set(npIdentifierToV8Identifier(propertyName),
......@@ -367,6 +366,7 @@ bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
if (context.IsEmpty())
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj(object->v8Object);
// FIXME: Verify that setting to undefined is right.
......@@ -387,6 +387,7 @@ bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
if (context.IsEmpty())
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj(object->v8Object);
return obj->Has(npIdentifierToV8Identifier(propertyName));
......@@ -410,6 +411,7 @@ bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
if (context.IsEmpty())
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj(object->v8Object);
v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodName));
......@@ -435,6 +437,8 @@ void _NPN_SetException(NPObject* npObject, const NPUTF8 *message)
return;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
V8Proxy::throwError(V8Proxy::GeneralError, message);
}
......@@ -451,6 +455,7 @@ bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint
if (context.IsEmpty())
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj(object->v8Object);
......@@ -505,6 +510,7 @@ bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uin
if (context.IsEmpty())
return false;
v8::Context::Scope scope(context);
ExceptionCatcher exceptionCatcher;
// Lookup the constructor function.
v8::Handle<v8::Object> ctorObj(object->v8Object);
......
......@@ -45,12 +45,12 @@
#include <v8.h>
namespace WebCore {
class DOMWindow;
static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0;
class DOMWindow;
WrapperTypeInfo* npObjectTypeInfo();
}
static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0;
WrapperTypeInfo* npObjectTypeInfo();
extern NPClass* npScriptObjectClass;
......@@ -59,7 +59,7 @@ extern NPClass* npScriptObjectClass;
struct V8NPObject {
NPObject object;
v8::Persistent<v8::Object> v8Object;
WebCore::DOMWindow* rootObject;
DOMWindow* rootObject;
};
struct PrivateIdentifier {
......@@ -70,8 +70,10 @@ struct PrivateIdentifier {
bool isString;
};
NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, WebCore::DOMWindow*);
NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, DOMWindow*);
NPObject* v8ObjectToNPObject(v8::Handle<v8::Object>);
} // namespace WebCore
#endif // NPV8Object_h
......@@ -45,7 +45,7 @@
#include "npruntime_priv.h"
#include <wtf/OwnArrayPtr.h>
using namespace WebCore;
namespace WebCore {
enum InvokeFunctionType {
InvokeMethod = 1,
......@@ -409,3 +409,5 @@ void forgetV8ObjectForNPObject(NPObject* object)
_NPN_ReleaseObject(object);
}
}
} // namespace WebCore
......@@ -39,6 +39,8 @@
#include <v8.h>
namespace WebCore {
// These functions can be replaced by normal JS operation.
// Getters
v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo&);
......@@ -65,4 +67,6 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*, NPObject* root);
// cannot be referred to.
void forgetV8ObjectForNPObject(NPObject*);
} // namespace WebCore
#endif // V8NPObject_h
......@@ -29,19 +29,18 @@
*/
#include "config.h"
#include "V8NPUtils.h"
#include "DOMWindow.h"
#include "Frame.h"
#include "PlatformString.h"
#undef LOG
#include "npruntime_impl.h"
#include "npruntime_priv.h"
#include "NPV8Object.h"
#include "V8NPObject.h"
#include "V8Proxy.h"
#include "npruntime_impl.h"
#include "npruntime_priv.h"
namespace WebCore {
void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result)
{
......@@ -69,7 +68,7 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP
char* utf8_chars = strdup(*utf8);
STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result);
} else if (object->IsObject()) {
WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext());
DOMWindow* window = V8Proxy::retrieveWindow(V8Proxy::currentContext());
NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window);
if (npobject)
_NPN_RegisterObject(npobject, owner);
......@@ -77,7 +76,6 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP
}
}
v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObject* npobject)
{
NPVariantType type = variant->type;
......@@ -128,3 +126,45 @@ NPIdentifier getStringIdentifier(v8::Handle<v8::String> str)
v8::String::Utf8Value utf8(str);
return _NPN_GetStringIdentifier(*utf8);
}
struct ExceptionHandlerInfo {
ExceptionHandlerInfo* previous;
ExceptionHandler handler;
void* data;
};
static ExceptionHandlerInfo* topHandler;
void pushExceptionHandler(ExceptionHandler handler, void* data)
{
ExceptionHandlerInfo* info = new ExceptionHandlerInfo;
info->previous = topHandler;
info->handler = handler;
info->data = data;
topHandler = info;
}
void popExceptionHandler()
{
ASSERT(topHandler);
ExceptionHandlerInfo* doomed = topHandler;
topHandler = topHandler->previous;
delete doomed;
}
ExceptionCatcher::ExceptionCatcher()
{
if (!topHandler)
m_tryCatch.SetVerbose(true);
}
ExceptionCatcher::~ExceptionCatcher()
{
if (!m_tryCatch.HasCaught())
return;
if (topHandler)
topHandler->handler(topHandler->data, *v8::String::Utf8Value(m_tryCatch.Exception()));
}
} // namespace WebCore
......@@ -38,6 +38,8 @@
#include <v8.h>
namespace WebCore {
// Convert a V8 Value of any type (string, bool, object, etc) to a NPVariant.
void convertV8ObjectToNPVariant(v8::Local<v8::Value>, NPObject*, NPVariant*);
......@@ -48,4 +50,22 @@ v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant*, NPObject*);
// Helper function to create an NPN String Identifier from a v8 string.
NPIdentifier getStringIdentifier(v8::Handle<v8::String>);
// The ExceptionHandler will be notified of any exceptions thrown while
// operating on a NPObject.
typedef void (*ExceptionHandler)(void* data, const NPUTF8* message);
void pushExceptionHandler(ExceptionHandler, void* data);
void popExceptionHandler();
// Upon destruction, an ExceptionCatcher will pass a caught exception to the
// current ExceptionHandler.
class ExceptionCatcher {
public:
ExceptionCatcher();
~ExceptionCatcher();
private:
v8::TryCatch m_tryCatch;
};
} // namespace WebCore
#endif // V8NPUtils_h
......@@ -35,6 +35,8 @@
#include <wtf/HashSet.h>
#include <wtf/Assertions.h>
using namespace WebCore;
// FIXME: Consider removing locks if we're singlethreaded already.
// The static initializer here should work okay, but we want to avoid
// static initialization in general.
......
2010-05-20 Darin Fisher <darin@chromium.org>
Reviewed by Nate Chapin.
[chromium] Provide a way to catch exceptions thrown while interacting
with a NPObject via WebBindings methods.
https://bugs.webkit.org/show_bug.cgi?id=39378
* public/WebBindings.h:
* src/WebBindings.cpp:
(WebKit::WebBindings::pushExceptionHandler):
(WebKit::WebBindings::popExceptionHandler):
2010-05-20 Jian Li <jianli@chromium.org>
Reviewed by David Levin.
......
......@@ -117,7 +117,7 @@ public:
// NPN_UTF8FromIdentifier
WEBKIT_API static NPUTF8* utf8FromIdentifier(NPIdentifier);
// Miscellaneous utility functions ------------------------------------
// Miscellaneous utility functions ----------------------------------------
// Complement to NPN_Get___Identifier functions. Extracts data from the NPIdentifier data
// structure. If isString is true upon return, string will be set but number's value is
......@@ -138,6 +138,15 @@ public:
// Return true (success) if the given npobj is a range object.
// If so, return that range as a WebRange object.
WEBKIT_API static bool getRange(NPObject* range, WebRange*);
// Exceptions -------------------------------------------------------------
typedef void (ExceptionHandler)(void* data, const NPUTF8* message);
// The exception handler will be notified of any exceptions thrown while
// operating on a NPObject.
WEBKIT_API static void pushExceptionHandler(ExceptionHandler, void* data);
WEBKIT_API static void popExceptionHandler();
};
} // namespace WebKit
......
......@@ -45,6 +45,7 @@
#include "V8DOMWrapper.h"
#include "V8Event.h"
#include "V8Helpers.h"
#include "V8NPUtils.h"
#include "V8Proxy.h"
#include "V8Range.h"
#elif USE(JSC)
......@@ -322,4 +323,14 @@ bool WebBindings::getRange(NPObject* range, WebRange* webrange)
#endif
}
void WebBindings::pushExceptionHandler(ExceptionHandler handler, void* data)
{
WebCore::pushExceptionHandler(handler, data);
}
void WebBindings::popExceptionHandler()
{
WebCore::popExceptionHandler();
}
} // namespace WebKit
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment