From 3d4b534a6833226e9cba41b1c694a4f4b6618445 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 2 Jul 2009 00:00:29 +0000 Subject: [PATCH] replace set_property/get_property with evaluate --- direct/src/plugin/p3dPythonRun.cxx | 59 ++++--------- direct/src/plugin/p3dSession.cxx | 35 ++------ direct/src/plugin/p3d_plugin.h | 67 ++++----------- direct/src/plugin_npapi/ppInstance.cxx | 104 ++++++++++++++++++++++- direct/src/plugin_npapi/ppInstance.h | 4 + direct/src/plugin_npapi/startup.cxx | 17 ++++ direct/src/plugin_standalone/panda3d.cxx | 70 +++------------ direct/src/plugin_standalone/panda3d.h | 5 -- direct/src/showutil/runp3d.py | 8 +- 9 files changed, 180 insertions(+), 189 deletions(-) diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index b9fd6e7206..4a18c12bc7 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -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, ¶ms, &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()); diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index ba1e9ef001..414cfb84fc 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -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 { diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index 03786be3f3..038b6caa5b 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -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); diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 8ed62ab4d3..807438c2c2 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -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; +} diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index 5935b564ef..e996c42e79 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -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; diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index 9565b8a0f2..1bf575174e 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -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; } diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index aad269e655..2f027fc191 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -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; diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index 1410ea2292..c43d66872d 100755 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -61,11 +61,6 @@ private: typedef pset 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 Properties; - Properties _properties; - // This nested class keeps track of active URL requests. class URLGetter { public: diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index 4aad84091e..e5eef215bc 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -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"