replace set_property/get_property with evaluate

This commit is contained in:
David Rose 2009-07-02 00:00:29 +00:00
parent fb630dc7cf
commit 3d4b534a68
9 changed files with 180 additions and 189 deletions

View File

@ -220,16 +220,21 @@ handle_command(TiXmlDocument *doc) {
} else if (strcmp(cmd, "feed_value") == 0) {
int instance_id, unique_id;
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
if (xvalue != (TiXmlElement *)NULL &&
xcommand->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS &&
if (xcommand->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS &&
xcommand->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
// TODO: deal with instance_id.
PyObject *value = from_xml_value(xvalue);
PyObject *result = PyObject_CallMethod
(_runner, (char*)"feedValue", (char*)"iO", unique_id, value);
Py_DECREF(value);
Py_XDECREF(result);
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
if (xvalue != NULL) {
PyObject *value = from_xml_value(xvalue);
PyObject *result = PyObject_CallMethod
(_runner, (char*)"feedValue", (char*)"iOi", unique_id, value, true);
Py_DECREF(value);
Py_XDECREF(result);
} else {
PyObject *result = PyObject_CallMethod
(_runner, (char*)"feedValue", (char*)"iOi", unique_id, Py_None, false);
Py_XDECREF(result);
}
}
} else {
@ -319,47 +324,19 @@ py_request_func(PyObject *args) {
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
} else if (strcmp(request_type, "get_property") == 0) {
// A get-property request.
const char *property_name;
} else if (strcmp(request_type, "evaluate") == 0) {
// An evaluate request.
const char *expression;
int unique_id;
if (!PyArg_ParseTuple(extra_args, "si", &property_name, &unique_id)) {
if (!PyArg_ParseTuple(extra_args, "si", &expression, &unique_id)) {
return NULL;
}
xrequest->SetAttribute("property_name", property_name);
xrequest->SetAttribute("expression", expression);
xrequest->SetAttribute("unique_id", unique_id);
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
} else if (strcmp(request_type, "set_property") == 0) {
// A set-property request.
const char *property_name;
PyObject *value;
if (!PyArg_ParseTuple(extra_args, "sO", &property_name, &value)) {
return NULL;
}
xrequest->SetAttribute("property_name", property_name);
xrequest->LinkEndChild(make_xml_value(value));
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
} else if (strcmp(request_type, "call") == 0) {
// A call-method request.
const char *property_name;
PyObject *params;
int unique_id;
if (!PyArg_ParseTuple(extra_args, "sOi", &property_name, &params, &unique_id)) {
return NULL;
}
xrequest->SetAttribute("property_name", property_name);
xrequest->SetAttribute("unique_id", unique_id);
xrequest->LinkEndChild(make_xml_value(params));
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
} else {
string message = string("Unsupported request type: ") + string(request_type);
PyErr_SetString(PyExc_ValueError, message.c_str());

View File

@ -450,37 +450,14 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
request->_request._notify._message = strdup(message);
}
} else if (strcmp(rtype, "get_property") == 0) {
const char *property_name = xrequest->Attribute("property_name");
} else if (strcmp(rtype, "evaluate") == 0) {
const char *expression = xrequest->Attribute("expression");
int unique_id;
if (property_name != NULL && xrequest->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
if (expression != NULL && xrequest->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
request = new P3D_request;
request->_request_type = P3D_RT_get_property;
request->_request._get_property._property_name = strdup(property_name);
request->_request._get_property._unique_id = unique_id;
}
} else if (strcmp(rtype, "set_property") == 0) {
const char *property_name = xrequest->Attribute("property_name");
TiXmlElement *xvalue = xrequest->FirstChildElement("value");
if (property_name != NULL && xvalue != NULL) {
request = new P3D_request;
request->_request_type = P3D_RT_set_property;
request->_request._set_property._property_name = strdup(property_name);
request->_request._set_property._value = rt_from_xml_value(xvalue);
}
} else if (strcmp(rtype, "call") == 0) {
const char *property_name = xrequest->Attribute("property_name");
TiXmlElement *xvalue = xrequest->FirstChildElement("value");
int unique_id;
if (property_name != NULL && xvalue != NULL &&
xrequest->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) {
request = new P3D_request;
request->_request_type = P3D_RT_call;
request->_request._call._property_name = strdup(property_name);
request->_request._call._params = rt_from_xml_value(xvalue);
request->_request._call._unique_id = unique_id;
request->_request_type = P3D_RT_evaluate;
request->_request._evaluate._expression = strdup(expression);
request->_request._evaluate._unique_id = unique_id;
}
} else {

View File

@ -451,9 +451,7 @@ typedef enum {
P3D_RT_get_url,
P3D_RT_post_url,
P3D_RT_notify,
P3D_RT_get_property,
P3D_RT_set_property,
P3D_RT_call,
P3D_RT_evaluate,
} P3D_request_type;
/* Structures corresponding to the request types in the above enum. */
@ -497,44 +495,18 @@ typedef struct {
const char *_message;
} P3D_request_notify;
/* A request to query a property on a host object. The property_name
will be a dot-delimited string corresponding to a nested object.
It should begin with "window." for the window object and
"document." for the DOM object that loaded the plugin. The host
should respond to this request by calling P3D_instance_feed_value()
with the given unique_id and the requested value, or NULL if the
named property does not exist. */
/* A request to evaluate a Javascript expression or statement. The
expression will be evaluated in the context of the parent window.
It is particularly useful for querying document state, such as
"document.form.username.value", or for changing this state, such as
"document.form.choose.red.select = 1". After evaluating the
expression, the host should return the response to this request by
calling P3D_instance_feed_value() with the given unique_id and the
result value, or NULL if there was an error with the expression. */
typedef struct {
const char *_property_name;
const char *_expression;
int _unique_id;
} P3D_request_get_property;
/* A request to change or set a property on a host object. The
property_name will be a dot-delimited string corresponding to a
nested object, as above. _value may be NULL to indicate a request
to delete the named property. The host does *not* receive
ownership of the _value pointer and should not store it or delete
it. The host need not respond to this event (other than by calling
P3D_request_finish()). */
typedef struct {
const char *_property_name;
const P3D_value *_value;
} P3D_request_set_property;
/* A request to call a function on a host object. The property_name
will be a dot-delimited string corresponding to a nested object, as
above. The _params pointer will be a list value, which contains
the parameter values to pass to the function. The host does not
receive ownership of the _params pointer and should not store it or
delete it. The host should respond to this request by calling
P3D_instance_feed_value() with the given unique_id and the return
value of the function, or NULL if the function does not exist or is
not a callable object. */
typedef struct {
const char *_property_name;
const P3D_value *_params;
int _unique_id;
} P3D_request_call;
} P3D_request_evaluate;
/* This is the overall structure that represents a single request. It
is returned by P3D_instance_get_request(). */
@ -546,9 +518,7 @@ typedef struct {
P3D_request_get_url _get_url;
P3D_request_post_url _post_url;
P3D_request_notify _notify;
P3D_request_get_property _get_property;
P3D_request_set_property _set_property;
P3D_request_call _call;
P3D_request_evaluate _evaluate;
} _request;
} P3D_request;
@ -650,13 +620,12 @@ P3D_instance_feed_url_stream_func(P3D_instance *instance, int unique_id,
const void *this_data,
size_t this_data_size);
/* This function is called by the host in response to a get_property
or call request. The instance and unique_id parameters are from
the original request; the value should be a freshly-allocated
P3D_value that represents the requested property value or the
return value from the function call, or NULL on error. Ownership
of the value value is passed into the plugin; the host should
*not* call P3D_value_finish() on this pointer. */
/* This function is called by the host in response to an evaulate
request. The instance and unique_id parameters are from the
original request; the value should be a freshly-allocated P3D_value
that represents the value of the evaluated expression, or NULL on
error. Ownership of the value value is passed into the plugin; the
host should *not* call P3D_value_finish() on this pointer. */
typedef void
P3D_instance_feed_value_func(P3D_instance *instance, int unique_id,
P3D_value *value);

View File

@ -369,7 +369,17 @@ handle_request(P3D_request *request) {
browser->geturlnotify(_npp_instance, request->_request._get_url._url,
NULL, req);
}
break;
case P3D_RT_evaluate:
{
logfile << "Got P3D_RT_evaluate: "
<< request->_request._evaluate._expression << "\n"
<< flush;
const string &expression = request->_request._evaluate._expression;
int unique_id = request->_request._evaluate._unique_id;
handle_evaluate(expression, unique_id);
}
break;
default:
@ -597,3 +607,95 @@ send_window() {
0, 0, _window.width, _window.height,
parent_window);
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::handle_evaluate
// Access: Private
// Description: Evaluates the script within the window, as requested
// by the Panda code.
////////////////////////////////////////////////////////////////////
void PPInstance::
handle_evaluate(const string &expression, int unique_id) {
NPObject *window = NULL;
if (browser->getvalue(_npp_instance, NPNVWindowNPObject, &window) == NPERR_NO_ERROR) {
logfile << "Got object for NPNVWindowNPObject: " << window << "\n";
NPString script;
script.utf8characters = expression.c_str();
script.utf8length = expression.length();
NPVariant result;
if (browser->evaluate(_npp_instance, window, &script, &result)) {
logfile << "Evaluated, result = ";
show_np_variant(result);
logfile << "\n" << flush;
P3D_value *value = np_variant_to_value(result);
browser->releasevariantvalue(&result);
P3D_instance_feed_value(_p3d_inst, unique_id, value);
} else {
logfile << "Couldn't evaluate\n";
}
} else {
logfile << "Couldn't get object for NPNVWindowNPObject\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::show_np_variant
// Access: Private
// Description: Outputs the variant value.
////////////////////////////////////////////////////////////////////
void PPInstance::
show_np_variant(const NPVariant &result) {
if (NPVARIANT_IS_NULL(result)) {
logfile << "null";
} else if (NPVARIANT_IS_VOID(result)) {
logfile << "void";
} else if (NPVARIANT_IS_BOOLEAN(result)) {
logfile << "bool " << NPVARIANT_TO_BOOLEAN(result);
} else if (NPVARIANT_IS_INT32(result)) {
logfile << "int " << NPVARIANT_TO_INT32(result);
} else if (NPVARIANT_IS_DOUBLE(result)) {
logfile << "double " << NPVARIANT_TO_DOUBLE(result);
} else if (NPVARIANT_IS_STRING(result)) {
NPString str = NPVARIANT_TO_STRING(result);
logfile << "string " << string(str.utf8characters, str.utf8length);
} else if (NPVARIANT_IS_OBJECT(result)) {
NPObject *child = NPVARIANT_TO_OBJECT(result);
logfile << "object " << child;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::np_variant_to_value
// Access: Private
// Description: Returns a fresly-allocated P3D_value object
// corresponding to the indicated NPVariant.
////////////////////////////////////////////////////////////////////
P3D_value *PPInstance::
np_variant_to_value(const NPVariant &result) {
if (NPVARIANT_IS_NULL(result)) {
return NULL;
} else if (NPVARIANT_IS_VOID(result)) {
return P3D_new_none_value();
} else if (NPVARIANT_IS_BOOLEAN(result)) {
return P3D_new_bool_value(NPVARIANT_TO_BOOLEAN(result));
} else if (NPVARIANT_IS_INT32(result)) {
return P3D_new_int_value(NPVARIANT_TO_INT32(result));
} else if (NPVARIANT_IS_DOUBLE(result)) {
return P3D_new_float_value(NPVARIANT_TO_DOUBLE(result));
} else if (NPVARIANT_IS_STRING(result)) {
NPString str = NPVARIANT_TO_STRING(result);
return P3D_new_string_value(str.utf8characters, str.utf8length);
} else if (NPVARIANT_IS_OBJECT(result)) {
// TODO?
return P3D_new_none_value();
// NPVARIANT_TO_OBJECT(result);
}
// Huh, what is this?
return NULL;
}

View File

@ -53,6 +53,10 @@ private:
void create_instance();
void send_window();
void handle_evaluate(const string &expression, int unique_id);
void show_np_variant(const NPVariant &result);
P3D_value *np_variant_to_value(const NPVariant &result);
private:
NPP _npp_instance;
unsigned int _npp_mode;

View File

@ -396,6 +396,23 @@ NPP_URLNotify(NPP instance, const char *url,
NPError
NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
logfile << "GetValue " << variable << "\n";
/*
if (variable == NPPVpluginScriptableNPObject) {
static NPObject *object = NULL;
if (object == NULL) {
static NPClass npclass;
memset(&npclass, 0, sizeof(npclass));
npclass.structVersion = NP_CLASS_STRUCT_VERSION;
object = browser->createobject(instance, &npclass);
assert(object != NULL);
}
*(NPObject **)value = object;
return NPERR_NO_ERROR;
}
*/
return NPERR_GENERIC_ERROR;
}

View File

@ -406,68 +406,18 @@ handle_request(P3D_request *request) {
// Ignore notifications.
break;
case P3D_RT_get_property:
cerr << "Got P3D_RT_get_property: "
<< request->_request._get_property._property_name << "\n";
case P3D_RT_evaluate:
cerr << "Got P3D_RT_evaluate: "
<< request->_request._evaluate._expression << "\n";
{
Properties::iterator pi =
_properties.find(request->_request._get_property._property_name);
if (pi != _properties.end()) {
// The named property has been set.
P3D_value *dup_value = P3D_value_copy((*pi).second);
P3D_instance_feed_value(request->_instance,
request->_request._get_property._unique_id,
dup_value);
} else {
// No such property set.
P3D_instance_feed_value(request->_instance,
request->_request._get_property._unique_id,
NULL);
}
handled = true;
}
break;
case P3D_RT_set_property:
cerr << "Got P3D_RT_set_property: "
<< request->_request._set_property._property_name << "\n";
{
// Also output the new value.
int buffer_size =
P3D_value_get_string_length(request->_request._set_property._value);
char *buffer = (char *)alloca(buffer_size);
P3D_value_extract_string(request->_request._set_property._value, buffer, buffer_size);
cerr.write(buffer, buffer_size);
cerr << "\n";
Properties::iterator pi =
_properties.insert(Properties::value_type(request->_request._set_property._property_name, NULL)).first;
if ((*pi).second != NULL) {
// Delete the original property.
P3D_value_finish((*pi).second);
}
(*pi).second =
P3D_value_copy(request->_request._set_property._value);
handled = true;
}
break;
case P3D_RT_call:
cerr << "Got P3D_RT_call: "
<< request->_request._call._property_name << "\n";
{
// Also output the parameter list.
int buffer_size =
P3D_value_get_string_length(request->_request._call._params);
char *buffer = (char *)alloca(buffer_size);
P3D_value_extract_string(request->_request._call._params, buffer, buffer_size);
cerr.write(buffer, buffer_size);
cerr << "\n";
// We don't have a mechanism for actually calling anything, though.
// In this standalone executable, every expression evaluates to
// itself as a string. We do this just to help debug the
// expression passing to and from the low-level Python code.
const string &expression = request->_request._evaluate._expression;
P3D_value *value = P3D_new_string_value(expression.data(), expression.length());
P3D_instance_feed_value(request->_instance,
request->_request._call._unique_id,
NULL);
request->_request._evaluate._unique_id,
value);
handled = true;
}
break;

View File

@ -61,11 +61,6 @@ private:
typedef pset<P3D_instance *> Instances;
Instances _instances;
// We maintain a table of properties in the "browser", mainly so we
// can test this feature of the core plugin API.
typedef pmap<string, P3D_value *> Properties;
Properties _properties;
// This nested class keeps track of active URL requests.
class URLGetter {
public:

View File

@ -234,11 +234,11 @@ class AppRunner(DirectObject):
def sendRequest(self, request, *args):
self.requestFunc(self.instanceId, request, args)
def feedValue(self, uniqueId, value):
""" Called by the host in response to a 'get_property' or
'call' request. """
def feedValue(self, uniqueId, value, success):
""" Called by the host in response to an 'evaluate'
request. """
print "feedValue(%s, %s)" % (uniqueId, value)
print "feedValue(%s, %s, %s)" % (uniqueId, value, success)
def windowEvent(self, win):
print "Got window event in runp3d"