Bug 556849 - '[OOPP] Reduce unnecessary HasProperty calls for plugin scriptable objects'. r=jst+josh+bsmedberg.
This commit is contained in:
Родитель
d1be5529e1
Коммит
bfd013c804
|
@ -92,10 +92,6 @@ both:
|
|||
rpc HasProperty(PPluginIdentifier aId)
|
||||
returns (bool aHasProperty);
|
||||
|
||||
rpc GetProperty(PPluginIdentifier aId)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
rpc SetProperty(PPluginIdentifier aId,
|
||||
Variant aValue)
|
||||
returns (bool aSuccess);
|
||||
|
@ -120,6 +116,24 @@ both:
|
|||
// temporarily protects the protocol object again for the duration of the call.
|
||||
async Protect();
|
||||
async Unprotect();
|
||||
|
||||
/**
|
||||
* GetProperty is slightly wonky due to the way we support NPObjects that have
|
||||
* methods and properties with the same name. When child calls parent we
|
||||
* simply return a property. When parent calls child, however, we need to do
|
||||
* several checks at once and return all the results simultaneously.
|
||||
*/
|
||||
parent:
|
||||
rpc GetParentProperty(PPluginIdentifier aId)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
child:
|
||||
rpc GetChildProperty(PPluginIdentifier aId)
|
||||
returns (bool aHasProperty,
|
||||
bool aHasMethod,
|
||||
Variant aResult,
|
||||
bool aSuccess);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -257,8 +257,8 @@ PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
|
|||
|
||||
Variant result;
|
||||
bool success;
|
||||
actor->CallGetProperty(static_cast<PPluginIdentifierChild*>(aName), &result,
|
||||
&success);
|
||||
actor->CallGetParentProperty(static_cast<PPluginIdentifierChild*>(aName),
|
||||
&result, &success);
|
||||
|
||||
if (!success) {
|
||||
return false;
|
||||
|
@ -831,45 +831,49 @@ PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId,
|
|||
}
|
||||
|
||||
bool
|
||||
PluginScriptableObjectChild::AnswerGetProperty(PPluginIdentifierChild* aId,
|
||||
Variant* aResult,
|
||||
bool* aSuccess)
|
||||
PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
|
||||
bool* aHasProperty,
|
||||
bool* aHasMethod,
|
||||
Variant* aResult,
|
||||
bool* aSuccess)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
*aHasProperty = *aHasMethod = *aSuccess = false;
|
||||
*aResult = void_t();
|
||||
|
||||
if (mInvalidated) {
|
||||
NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
|
||||
*aResult = void_t();
|
||||
*aSuccess = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
|
||||
NS_ASSERTION(mType == LocalObject, "Bad type!");
|
||||
|
||||
if (!(mObject->_class && mObject->_class->getProperty)) {
|
||||
*aResult = void_t();
|
||||
*aSuccess = false;
|
||||
if (!(mObject->_class && mObject->_class->hasProperty &&
|
||||
mObject->_class->hasMethod && mObject->_class->getProperty)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT(result);
|
||||
PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
|
||||
if (!mObject->_class->getProperty(mObject, id->ToNPIdentifier(), &result)) {
|
||||
*aResult = void_t();
|
||||
*aSuccess = false;
|
||||
return true;
|
||||
}
|
||||
NPIdentifier id = static_cast<PluginIdentifierChild*>(aId)->ToNPIdentifier();
|
||||
|
||||
Variant converted;
|
||||
if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(),
|
||||
false))) {
|
||||
DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
|
||||
*aResult = converted;
|
||||
}
|
||||
else {
|
||||
*aResult = void_t();
|
||||
*aHasProperty = mObject->_class->hasProperty(mObject, id);
|
||||
*aHasMethod = mObject->_class->hasMethod(mObject, id);
|
||||
|
||||
if (*aHasProperty) {
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT(result);
|
||||
|
||||
if (!mObject->_class->getProperty(mObject, id, &result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Variant converted;
|
||||
if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(),
|
||||
false))) {
|
||||
DeferNPVariantLastRelease(&PluginModuleChild::sBrowserFuncs, &result);
|
||||
*aResult = converted;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -891,7 +895,15 @@ PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
|
|||
NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
|
||||
NS_ASSERTION(mType == LocalObject, "Bad type!");
|
||||
|
||||
if (!(mObject->_class && mObject->_class->setProperty)) {
|
||||
if (!(mObject->_class && mObject->_class->hasProperty &&
|
||||
mObject->_class->setProperty)) {
|
||||
*aSuccess = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
NPIdentifier id = static_cast<PluginIdentifierChild*>(aId)->ToNPIdentifier();
|
||||
|
||||
if (!mObject->_class->hasProperty(mObject, id)) {
|
||||
*aSuccess = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -899,9 +911,7 @@ PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
|
|||
NPVariant converted;
|
||||
ConvertToVariant(aValue, converted);
|
||||
|
||||
PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
|
||||
if ((*aSuccess = mObject->_class->setProperty(mObject, id->ToNPIdentifier(),
|
||||
&converted))) {
|
||||
if ((*aSuccess = mObject->_class->setProperty(mObject, id, &converted))) {
|
||||
PluginModuleChild::sBrowserFuncs.releasevariantvalue(&converted);
|
||||
}
|
||||
return true;
|
||||
|
@ -922,13 +932,17 @@ PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
|
|||
NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
|
||||
NS_ASSERTION(mType == LocalObject, "Bad type!");
|
||||
|
||||
if (!(mObject->_class && mObject->_class->removeProperty)) {
|
||||
if (!(mObject->_class && mObject->_class->hasProperty &&
|
||||
mObject->_class->removeProperty)) {
|
||||
*aSuccess = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
|
||||
*aSuccess = mObject->_class->removeProperty(mObject, id->ToNPIdentifier());
|
||||
NPIdentifier id = static_cast<PluginIdentifierChild*>(aId)->ToNPIdentifier();
|
||||
*aSuccess = mObject->_class->hasProperty(mObject, id) ?
|
||||
mObject->_class->removeProperty(mObject, id) :
|
||||
true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,9 +107,11 @@ public:
|
|||
bool* aHasProperty);
|
||||
|
||||
virtual bool
|
||||
AnswerGetProperty(PPluginIdentifierChild* aId,
|
||||
Variant* aResult,
|
||||
bool* aSuccess);
|
||||
AnswerGetChildProperty(PPluginIdentifierChild* aId,
|
||||
bool* aHasProperty,
|
||||
bool* aHasMethod,
|
||||
Variant* aResult,
|
||||
bool* aSuccess);
|
||||
|
||||
virtual bool
|
||||
AnswerSetProperty(PPluginIdentifierChild* aId,
|
||||
|
|
|
@ -321,46 +321,9 @@ PluginScriptableObjectParent::ScriptableGetProperty(NPObject* aObject,
|
|||
NPIdentifier aName,
|
||||
NPVariant* aResult)
|
||||
{
|
||||
if (aObject->_class != GetClass()) {
|
||||
NS_ERROR("Don't know what kind of object this is!");
|
||||
return false;
|
||||
}
|
||||
|
||||
ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
|
||||
if (object->invalidated) {
|
||||
NS_WARNING("Calling method on an invalidated object!");
|
||||
return false;
|
||||
}
|
||||
|
||||
PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
|
||||
if (!identifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
|
||||
if (!actor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
|
||||
|
||||
Variant result;
|
||||
bool success;
|
||||
if (!actor->CallGetProperty(identifier, &result, &success)) {
|
||||
NS_WARNING("Failed to send message!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ConvertToVariant(result, *aResult, actor->GetInstance())) {
|
||||
NS_WARNING("Failed to convert result!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// See GetPropertyHelper below.
|
||||
NS_NOTREACHED("Shouldn't ever call this directly!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -964,9 +927,10 @@ PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId,
|
|||
}
|
||||
|
||||
bool
|
||||
PluginScriptableObjectParent::AnswerGetProperty(PPluginIdentifierParent* aId,
|
||||
Variant* aResult,
|
||||
bool* aSuccess)
|
||||
PluginScriptableObjectParent::AnswerGetParentProperty(
|
||||
PPluginIdentifierParent* aId,
|
||||
Variant* aResult,
|
||||
bool* aSuccess)
|
||||
{
|
||||
if (!mObject) {
|
||||
NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
|
||||
|
@ -1287,3 +1251,43 @@ PluginScriptableObjectParent::AnswerNPN_Evaluate(const nsCString& aScript,
|
|||
*aResult = convertedResult;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
PluginScriptableObjectParent::GetPropertyHelper(NPIdentifier aName,
|
||||
PRBool* aHasProperty,
|
||||
PRBool* aHasMethod,
|
||||
NPVariant* aResult)
|
||||
{
|
||||
NS_ASSERTION(Type() == Proxy, "Bad type!");
|
||||
|
||||
ParentNPObject* object = static_cast<ParentNPObject*>(mObject);
|
||||
if (object->invalidated) {
|
||||
NS_WARNING("Calling method on an invalidated object!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
PPluginIdentifierParent* identifier = GetIdentifier(GetInstance(), aName);
|
||||
if (!identifier) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
bool hasProperty, hasMethod, success;
|
||||
Variant result;
|
||||
if (!CallGetChildProperty(identifier, &hasProperty, &hasMethod, &result,
|
||||
&success)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!ConvertToVariant(result, *aResult, GetInstance())) {
|
||||
NS_WARNING("Failed to convert result!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*aHasProperty = hasProperty;
|
||||
*aHasMethod = hasMethod;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "mozilla/plugins/PPluginScriptableObjectParent.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "npfunctions.h"
|
||||
#include "npruntime.h"
|
||||
|
||||
|
@ -96,9 +97,9 @@ public:
|
|||
bool* aHasProperty);
|
||||
|
||||
virtual bool
|
||||
AnswerGetProperty(PPluginIdentifierParent* aId,
|
||||
Variant* aResult,
|
||||
bool* aSuccess);
|
||||
AnswerGetParentProperty(PPluginIdentifierParent* aId,
|
||||
Variant* aResult,
|
||||
bool* aSuccess);
|
||||
|
||||
virtual bool
|
||||
AnswerSetProperty(PPluginIdentifierParent* aId,
|
||||
|
@ -168,6 +169,11 @@ public:
|
|||
return mType;
|
||||
}
|
||||
|
||||
JSBool GetPropertyHelper(NPIdentifier aName,
|
||||
PRBool* aHasProperty,
|
||||
PRBool* aHasMethod,
|
||||
NPVariant* aResult);
|
||||
|
||||
private:
|
||||
static NPObject*
|
||||
ScriptableAllocate(NPP aInstance,
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
#include "base/basictypes.h"
|
||||
#endif
|
||||
|
||||
// FIXME(bug 332648): Give me a real API please!
|
||||
#include "jscntxt.h"
|
||||
|
||||
|
@ -55,6 +59,12 @@
|
|||
|
||||
using namespace mozilla::plugins::parent;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
#include "mozilla/plugins/PluginScriptableObjectParent.h"
|
||||
using mozilla::plugins::PluginScriptableObjectParent;
|
||||
using mozilla::plugins::ParentNPObject;
|
||||
#endif
|
||||
|
||||
// Hash of JSObject wrappers that wraps JSObjects as NPObjects. There
|
||||
// will be one wrapper per JSObject per plugin instance, i.e. if two
|
||||
// plugins access the JSObject x, two wrappers for x will be
|
||||
|
@ -82,6 +92,20 @@ static nsIJSContextStack *sContextStack;
|
|||
|
||||
static nsTArray<NPObject*>* sDelayedReleases;
|
||||
|
||||
namespace {
|
||||
|
||||
inline bool
|
||||
NPObjectIsOutOfProcessProxy(NPObject *obj)
|
||||
{
|
||||
#ifdef MOZ_IPC
|
||||
return obj->_class == PluginScriptableObjectParent::GetClass();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Helper class that reports any JS exceptions that were thrown while
|
||||
// the plugin executed JS.
|
||||
|
||||
|
@ -155,8 +179,8 @@ NPObjWrapper_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
jsval *rval);
|
||||
|
||||
static JSBool
|
||||
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj,
|
||||
NPObject *npobj, jsval id, jsval *vp);
|
||||
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject *npobj,
|
||||
jsval id, NPVariant* getPropertyResult, jsval *vp);
|
||||
|
||||
static JSClass sNPObjectJSWrapperClass =
|
||||
{
|
||||
|
@ -1182,6 +1206,10 @@ NPObjWrapper_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (NPObjectIsOutOfProcessProxy(npobj)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PluginDestructionGuard pdg(LookupNPP(npobj));
|
||||
|
||||
JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
|
@ -1220,12 +1248,14 @@ NPObjWrapper_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
PluginDestructionGuard pdg(LookupNPP(npobj));
|
||||
|
||||
JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
if (!NPObjectIsOutOfProcessProxy(npobj)) {
|
||||
JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!hasProperty)
|
||||
return JS_TRUE;
|
||||
if (!hasProperty)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (!npobj->_class->removeProperty(npobj, (NPIdentifier)id))
|
||||
*vp = JSVAL_FALSE;
|
||||
|
@ -1257,14 +1287,16 @@ NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
PluginDestructionGuard pdg(npp);
|
||||
|
||||
JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
if (!NPObjectIsOutOfProcessProxy(npobj)) {
|
||||
JSBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!hasProperty) {
|
||||
ThrowJSException(cx, "Trying to set unsupported property on NPObject!");
|
||||
if (!hasProperty) {
|
||||
ThrowJSException(cx, "Trying to set unsupported property on NPObject!");
|
||||
|
||||
return JS_FALSE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
NPVariant npv;
|
||||
|
@ -1311,22 +1343,53 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
PluginDestructionGuard pdg(npp);
|
||||
|
||||
PRBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
PRBool hasProperty, hasMethod;
|
||||
|
||||
NPVariant npv;
|
||||
VOID_TO_NPVARIANT(npv);
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (NPObjectIsOutOfProcessProxy(npobj)) {
|
||||
PluginScriptableObjectParent* actor =
|
||||
static_cast<ParentNPObject*>(npobj)->parent;
|
||||
JSBool success = actor->GetPropertyHelper((NPIdentifier)id, &hasProperty,
|
||||
&hasMethod, &npv);
|
||||
if (!ReportExceptionIfPending(cx)) {
|
||||
if (success)
|
||||
_releasevariantvalue(&npv);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
// We return NPObject Member class here to support ambiguous members.
|
||||
if (hasProperty && hasMethod)
|
||||
return CreateNPObjectMember(npp, cx, obj, npobj, id, &npv, vp);
|
||||
|
||||
if (hasProperty) {
|
||||
*vp = NPVariantToJSVal(npp, cx, &npv);
|
||||
_releasevariantvalue(&npv);
|
||||
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
PRBool hasMethod = npobj->_class->hasMethod(npobj, (NPIdentifier)id);
|
||||
hasMethod = npobj->_class->hasMethod(npobj, (NPIdentifier)id);
|
||||
if (!ReportExceptionIfPending(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
// We return NPObject Member class here to support ambiguous members.
|
||||
if (hasProperty && hasMethod)
|
||||
return CreateNPObjectMember(npp, cx, obj, npobj, id, vp);
|
||||
return CreateNPObjectMember(npp, cx, obj, npobj, id, nsnull, vp);
|
||||
|
||||
if (hasProperty) {
|
||||
NPVariant npv;
|
||||
VOID_TO_NPVARIANT(npv);
|
||||
|
||||
if (npobj->_class->getProperty(npobj, (NPIdentifier)id, &npv))
|
||||
*vp = NPVariantToJSVal(npp, cx, &npv);
|
||||
|
||||
|
@ -2048,8 +2111,8 @@ LookupNPP(NPObject *npobj)
|
|||
}
|
||||
|
||||
JSBool
|
||||
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj,
|
||||
NPObject* npobj, jsval id, jsval *vp)
|
||||
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
|
||||
jsval id, NPVariant* getPropertyResult, jsval *vp)
|
||||
{
|
||||
NS_ENSURE_TRUE(vp, JS_FALSE);
|
||||
|
||||
|
@ -2082,18 +2145,27 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj,
|
|||
|
||||
jsval fieldValue;
|
||||
NPVariant npv;
|
||||
VOID_TO_NPVARIANT(npv);
|
||||
NPBool hasProperty;
|
||||
|
||||
NPBool hasProperty = npobj->_class->getProperty(npobj, (NPIdentifier)id,
|
||||
&npv);
|
||||
if (ReportExceptionIfPending(cx)) {
|
||||
::JS_RemoveRoot(cx, vp);
|
||||
return JS_FALSE;
|
||||
if (getPropertyResult) {
|
||||
// Plugin has already handed us the value we want here.
|
||||
npv = *getPropertyResult;
|
||||
hasProperty = true;
|
||||
}
|
||||
else {
|
||||
VOID_TO_NPVARIANT(npv);
|
||||
|
||||
if (!hasProperty) {
|
||||
::JS_RemoveRoot(cx, vp);
|
||||
return JS_FALSE;
|
||||
NPBool hasProperty = npobj->_class->getProperty(npobj, (NPIdentifier)id,
|
||||
&npv);
|
||||
if (!ReportExceptionIfPending(cx)) {
|
||||
::JS_RemoveRoot(cx, vp);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!hasProperty) {
|
||||
::JS_RemoveRoot(cx, vp);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
fieldValue = NPVariantToJSVal(npp, cx, &npv);
|
||||
|
|
|
@ -85,6 +85,7 @@ _MOCHITEST_FILES = \
|
|||
test_hanging.html \
|
||||
crashing_subpage.html \
|
||||
test_GCrace.html \
|
||||
test_propertyAndMethod.html \
|
||||
$(NULL)
|
||||
|
||||
# test_npruntime_npnsetexception.html \ Disabled for e10s
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>NPObject with property and method with the same name</title>
|
||||
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
||||
<body onload="run()">
|
||||
|
||||
<embed id="plugin" type="application/x-test" wmode="window"></embed>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
if (typeof Object.getPrototypeOf !== "function") {
|
||||
if (typeof "test".__proto__ === "object") {
|
||||
Object.getPrototypeOf = function(object) {
|
||||
return object.__proto__;
|
||||
};
|
||||
} else {
|
||||
Object.getPrototypeOf = function(object) {
|
||||
// May break if the constructor has been tampered with
|
||||
return object.constructor.prototype;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function run() {
|
||||
var plugin = document.getElementById("plugin");
|
||||
var pluginProto = Object.getPrototypeOf(plugin);
|
||||
|
||||
delete pluginProto.propertyAndMethod;
|
||||
ok(isNaN(plugin.propertyAndMethod + 0), "Shouldn't be set yet!");
|
||||
|
||||
plugin.propertyAndMethod = 5;
|
||||
is(plugin.propertyAndMethod, 5, "Should be set to 5!");
|
||||
|
||||
delete pluginProto.propertyAndMethod;
|
||||
ok(isNaN(plugin.propertyAndMethod + 0), "Shouldn't be set any more!");
|
||||
|
||||
var res = plugin.propertyAndMethod();
|
||||
is(res, 5, "Method invocation should return 5!");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -157,6 +157,7 @@ static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount
|
|||
static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
static bool propertyAndMethod(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
|
||||
static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
||||
"npnEvaluateTest",
|
||||
|
@ -199,6 +200,7 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
|||
"getClipboardText",
|
||||
"callOnDestroy",
|
||||
"reinitWidget",
|
||||
"propertyAndMethod"
|
||||
};
|
||||
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
|
||||
static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMethodIdentifierNames)] = {
|
||||
|
@ -242,7 +244,13 @@ static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMetho
|
|||
getClipboardText,
|
||||
callOnDestroy,
|
||||
reinitWidget,
|
||||
propertyAndMethod
|
||||
};
|
||||
static const NPUTF8* sPluginPropertyIdentifierNames[] = {
|
||||
"propertyAndMethod"
|
||||
};
|
||||
static NPIdentifier sPluginPropertyIdentifiers[ARRAY_LENGTH(sPluginPropertyIdentifierNames)];
|
||||
static NPVariant sPluginPropertyValues[ARRAY_LENGTH(sPluginPropertyIdentifierNames)];
|
||||
|
||||
struct URLNotifyData
|
||||
{
|
||||
|
@ -307,6 +315,9 @@ static void initializeIdentifiers()
|
|||
if (!sIdentifiersInitialized) {
|
||||
NPN_GetStringIdentifiers(sPluginMethodIdentifierNames,
|
||||
ARRAY_LENGTH(sPluginMethodIdentifierNames), sPluginMethodIdentifiers);
|
||||
NPN_GetStringIdentifiers(sPluginPropertyIdentifierNames,
|
||||
ARRAY_LENGTH(sPluginPropertyIdentifierNames), sPluginPropertyIdentifiers);
|
||||
|
||||
sIdentifiersInitialized = true;
|
||||
|
||||
// Check whether NULL is handled in NPN_GetStringIdentifiers
|
||||
|
@ -320,6 +331,9 @@ static void clearIdentifiers()
|
|||
{
|
||||
memset(sPluginMethodIdentifiers, 0,
|
||||
ARRAY_LENGTH(sPluginMethodIdentifiers) * sizeof(NPIdentifier));
|
||||
memset(sPluginPropertyIdentifiers, 0,
|
||||
ARRAY_LENGTH(sPluginPropertyIdentifiers) * sizeof(NPIdentifier));
|
||||
|
||||
sIdentifiersInitialized = false;
|
||||
}
|
||||
|
||||
|
@ -446,6 +460,25 @@ getFuncFromString(const char* funcname)
|
|||
return FUNCTION_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
DuplicateNPVariant(NPVariant& aDest, const NPVariant& aSrc)
|
||||
{
|
||||
if (NPVARIANT_IS_STRING(aSrc)) {
|
||||
NPString src = NPVARIANT_TO_STRING(aSrc);
|
||||
char* buf = new char[src.UTF8Length];
|
||||
strncpy(buf, src.UTF8Characters, src.UTF8Length);
|
||||
STRINGN_TO_NPVARIANT(buf, src.UTF8Length, aDest);
|
||||
}
|
||||
else if (NPVARIANT_IS_OBJECT(aSrc)) {
|
||||
NPObject* obj =
|
||||
NPN_RetainObject(NPVARIANT_TO_OBJECT(aSrc));
|
||||
OBJECT_TO_NPVARIANT(obj, aDest);
|
||||
}
|
||||
else {
|
||||
aDest = aSrc;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// function signatures
|
||||
//
|
||||
|
@ -533,6 +566,10 @@ NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs)
|
|||
|
||||
initializeIdentifiers();
|
||||
|
||||
for (int i = 0; i < ARRAY_LENGTH(sPluginPropertyValues); i++) {
|
||||
VOID_TO_NPVARIANT(sPluginPropertyValues[i]);
|
||||
}
|
||||
|
||||
memset(&sNPClass, 0, sizeof(NPClass));
|
||||
sNPClass.structVersion = NP_CLASS_STRUCT_VERSION;
|
||||
sNPClass.allocate = (NPAllocateFunctionPtr)scriptableAllocate;
|
||||
|
@ -575,6 +612,10 @@ NPError OSCALL NP_Shutdown()
|
|||
{
|
||||
clearIdentifiers();
|
||||
|
||||
for (int i = 0; i < ARRAY_LENGTH(sPluginPropertyValues); i++) {
|
||||
NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
|
||||
}
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1544,24 +1585,47 @@ scriptableInvokeDefault(NPObject* npobj, const NPVariant* args, uint32_t argCoun
|
|||
bool
|
||||
scriptableHasProperty(NPObject* npobj, NPIdentifier name)
|
||||
{
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
|
||||
if (name == sPluginPropertyIdentifiers[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
scriptableGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result)
|
||||
{
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
|
||||
if (name == sPluginPropertyIdentifiers[i]) {
|
||||
DuplicateNPVariant(*result, sPluginPropertyValues[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
scriptableSetProperty(NPObject* npobj, NPIdentifier name, const NPVariant* value)
|
||||
{
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
|
||||
if (name == sPluginPropertyIdentifiers[i]) {
|
||||
NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
|
||||
DuplicateNPVariant(sPluginPropertyValues[i], *value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
scriptableRemoveProperty(NPObject* npobj, NPIdentifier name)
|
||||
{
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
|
||||
if (name == sPluginPropertyIdentifiers[i]) {
|
||||
NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2687,3 +2751,11 @@ reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
|||
pluginWidgetInit(id, id->window.window);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
propertyAndMethod(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||
NPVariant* result)
|
||||
{
|
||||
INT32_TO_NPVARIANT(5, *result);
|
||||
return true;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче