a tiny bit of cleanup

This commit is contained in:
David Rose 2009-07-07 18:14:27 +00:00
parent 25dd6bcc71
commit 41ba4f06cb
6 changed files with 130 additions and 152 deletions

View File

@ -20,8 +20,7 @@
#include "p3dSplashWindow.h"
#include "p3dWinSplashWindow.h"
#include "p3dObject.h"
#include "p3dNoneObject.h"
#include "p3dPythonObject.h"
#include "p3dNullObject.h"
#include <sstream>
#include <algorithm>
@ -84,7 +83,6 @@ P3DInstance::
_packages.clear();
if (_splash_window != NULL) {
nout << "Deleting splash window in destructor\n" << flush;
delete _splash_window;
_splash_window = NULL;
}
@ -93,8 +91,6 @@ P3DInstance::
// TODO: Is it possible for someone to delete an instance while a
// download is still running? Who will crash when this happens?
nout << "deleting instance " << this << "\n" << flush;
}
////////////////////////////////////////////////////////////////////
@ -176,7 +172,6 @@ set_wparams(const P3DWindowParams &wparams) {
P3D_object *P3DInstance::
get_panda_script_object() const {
assert(_session != NULL);
nout << "Called P3DInstance::get_panda_script_object()\n";
TiXmlDocument *doc = new TiXmlDocument;
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
@ -186,7 +181,6 @@ get_panda_script_object() const {
doc->LinkEndChild(decl);
doc->LinkEndChild(xcommand);
TiXmlDocument *response = _session->command_and_response(doc);
nout << "response pointer: " << response << "\n" << flush;
P3D_object *result = NULL;
if (response != NULL) {
@ -200,10 +194,10 @@ get_panda_script_object() const {
delete response;
}
nout << "Returning " << result << "\n" << flush;
if (result != NULL) {
nout << "result = " << *result << "\n" << flush;
if (result == NULL) {
result = new P3DNullObject;
}
return result;
}
@ -217,7 +211,6 @@ get_panda_script_object() const {
////////////////////////////////////////////////////////////////////
void P3DInstance::
set_browser_script_object(P3D_object *browser_script_object) {
nout << "Called P3DInstance::set_browser_script_object()\n";
if (browser_script_object != _browser_script_object) {
if (_browser_script_object != NULL) {
P3D_OBJECT_FINISH(_browser_script_object);
@ -265,8 +258,6 @@ get_request() {
}
RELEASE_LOCK(_request_lock);
nout << "get_request: " << result << "\n" << flush;
if (result != NULL) {
switch (result->_request_type) {
case P3D_RT_notify:
@ -295,8 +286,6 @@ get_request() {
////////////////////////////////////////////////////////////////////
void P3DInstance::
add_request(P3D_request *request) {
nout << "Instance " << this << " add_request(" << request->_request_type
<< ")\n" << flush;
request->_instance = this;
ACQUIRE_LOCK(_request_lock);
@ -353,7 +342,6 @@ feed_url_stream(int unique_id,
if (!download_ok || download->get_download_finished()) {
// All done.
nout << "completed download " << unique_id << "\n" << flush;
_downloads.erase(di);
delete download;
}
@ -398,9 +386,6 @@ start_download(P3DDownload *download) {
bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second;
assert(inserted);
nout << "beginning download " << download_id << ": " << download->get_url()
<< "\n" << flush;
P3D_request *request = new P3D_request;
request->_request_type = P3D_RT_get_url;
request->_request._get_url._url = strdup(download->get_url().c_str());
@ -489,10 +474,8 @@ handle_notify_request(P3D_request *request) {
if (strcmp(message, "onwindowopen") == 0) {
// The process told us that it just succesfully opened its
// window.
nout << "Instance " << this << " got onwindowopen\n" << flush;
_instance_window_opened = true;
if (_splash_window != NULL) {
nout << "Deleting splash window\n" << flush;
delete _splash_window;
_splash_window = NULL;
}
@ -515,14 +498,7 @@ handle_script_request(P3D_request *request) {
case P3D_SO_get_property:
{
P3D_object *result = P3D_OBJECT_GET_PROPERTY(object, request->_request._script._property_name);
nout << "get_property, object = " << object << "\n";
if (object != NULL) {
nout << " *object = " << *object << "\n" << flush;
}
nout << "result = " << result << "\n" << flush;
if (result != NULL) {
nout << " *result = " << *result << "\n" << flush;
}
// We've got the property value; feed it back down to the
// subprocess.
TiXmlDocument *doc = new TiXmlDocument;
@ -546,11 +522,6 @@ handle_script_request(P3D_request *request) {
{
bool result = P3D_OBJECT_SET_PROPERTY(object, request->_request._script._property_name,
request->_request._script._value);
nout << "set_property, object = " << object << "\n";
if (object != NULL) {
nout << " *object = " << *object << "\n" << flush;
}
nout << "result = " << result << "\n" << flush;
// Feed the result back down to the subprocess.
TiXmlDocument *doc = new TiXmlDocument;
@ -575,11 +546,6 @@ handle_script_request(P3D_request *request) {
{
bool result = P3D_OBJECT_SET_PROPERTY(object, request->_request._script._property_name,
NULL);
nout << "del_property, object = " << object << "\n";
if (object != NULL) {
nout << " *object = " << *object << "\n" << flush;
}
nout << "result = " << result << "\n" << flush;
// Feed the result back down to the subprocess.
TiXmlDocument *doc = new TiXmlDocument;
@ -634,8 +600,6 @@ make_splash_window() {
string filename = name;
free(name);
nout << "Downloading splash image into " << filename << "\n";
// Start downloading the requested splash image.
SplashDownload *download = new SplashDownload(this);
download->set_url(splash_image_url);

View File

@ -191,14 +191,12 @@ run_python() {
task_mgr->add(_check_comm_task);
// Finally, get lost in taskMgr.run().
nout << "calling run()\n";
PyObject *done = PyObject_CallMethod(_taskMgr, (char *)"run", (char *)"");
if (done == NULL) {
PyErr_Print();
return false;
}
Py_DECREF(done);
nout << "done calling run()\n";
return true;
}
@ -211,7 +209,6 @@ run_python() {
////////////////////////////////////////////////////////////////////
void P3DPythonRun::
handle_command(TiXmlDocument *doc) {
nout << "got command: " << *doc << "\n";
TiXmlElement *xcommand = doc->FirstChildElement("command");
if (xcommand != NULL) {
bool needs_response = false;
@ -270,7 +267,6 @@ handle_command(TiXmlDocument *doc) {
xresponse->SetAttribute("response_id", want_response_id);
doc.LinkEndChild(decl);
doc.LinkEndChild(xresponse);
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
}
}
@ -298,7 +294,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
if (op != NULL) {
if (strcmp(op, "get_panda_script_object") == 0) {
// Get Panda's toplevel Python object.
PyObject *obj = PyObject_GetAttrString(_runner, "scriptRoot");
PyObject *obj = PyObject_CallMethod(_runner, "getPandaScriptObject", (char *)"");
if (obj != NULL) {
xresponse->LinkEndChild(pyobj_to_xml(obj));
Py_DECREF(obj);
@ -417,7 +413,6 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
}
if (needs_response) {
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
}
}
@ -554,23 +549,19 @@ py_request_func(PyObject *args) {
return NULL;
}
nout << "Waiting for script_response " << response_id << "\n";
TiXmlDocument *doc = wait_script_response(response_id);
nout << "got: " << *doc << "\n";
TiXmlElement *xcommand = doc->FirstChildElement("command");
assert(xcommand != NULL);
TiXmlElement *xvalue = xcommand->FirstChildElement("value");
PyObject *value = NULL;
if (xvalue != NULL) {
nout << "Converting xvalue: " << *xvalue << "\n";
value = xml_to_pyobj(xvalue);
} else {
// An absence of a <value> element means a NULL pointer.
value = _null;
Py_INCREF(value);
}
nout << "Got script_response " << response_id << ", xvalue = " << xvalue << "\n";
delete doc;
Py_DECREF(extra_args);
@ -594,7 +585,6 @@ py_request_func(PyObject *args) {
}
xrequest->SetAttribute("message", message);
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
} else if (strcmp(request_type, "script") == 0) {
@ -619,25 +609,8 @@ py_request_func(PyObject *args) {
TiXmlElement *xvalue = pyobj_to_xml(value);
xrequest->LinkEndChild(xvalue);
nout << "sending " << doc << "\n" << flush;
_pipe_write << doc << flush;
/*
} else if (strcmp(request_type, "evaluate") == 0) {
// An evaluate request.
const char *expression;
int unique_id;
if (!PyArg_ParseTuple(extra_args, "si", &expression, &unique_id)) {
Py_DECREF(extra_args);
return NULL;
}
xrequest->SetAttribute("expression", expression);
xrequest->SetAttribute("unique_id", unique_id);
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());
@ -687,12 +660,10 @@ spawn_read_thread() {
////////////////////////////////////////////////////////////////////
void P3DPythonRun::
join_read_thread() {
nout << "waiting for thread\n";
_read_thread_continue = false;
_pipe_read.close();
JOIN_THREAD(_read_thread);
nout << "done waiting for thread\n";
}
////////////////////////////////////////////////////////////////////
@ -703,7 +674,6 @@ join_read_thread() {
////////////////////////////////////////////////////////////////////
void P3DPythonRun::
start_instance(P3DCInstance *inst, TiXmlElement *xinstance) {
nout << "starting instance " << inst << "\n";
_instances[inst->get_instance_id()] = inst;
TiXmlElement *xfparams = xinstance->FirstChildElement("fparams");
@ -861,14 +831,12 @@ terminate_session() {
}
_instances.clear();
nout << "calling stop()\n";
PyObject *result = PyObject_CallMethod(_taskMgr, (char *)"stop", (char *)"");
if (result == NULL) {
PyErr_Print();
return;
}
Py_DECREF(result);
nout << "done calling stop()\n";
// The task manager is cleaned up. Let's exit immediately here,
// rather than returning all the way up. This just makes it easier
@ -1045,14 +1013,12 @@ xml_to_pyobj(TiXmlElement *xvalue) {
////////////////////////////////////////////////////////////////////
void P3DPythonRun::
rt_thread_run() {
nout << "thread reading.\n";
while (_read_thread_continue) {
TiXmlDocument *doc = new TiXmlDocument;
_pipe_read >> *doc;
if (!_pipe_read || _pipe_read.eof()) {
// Some error on reading. Abort.
nout << "Error on reading.\n";
_program_continue = false;
return;
}

View File

@ -214,7 +214,6 @@ void P3DSession::
send_command(TiXmlDocument *command) {
if (_p3dpython_running) {
// Python is running. Send the command.
nout << "Sending " << *command << "\n" << flush;
_pipe_write << *command << flush;
delete command;
} else {
@ -258,7 +257,6 @@ command_and_response(TiXmlDocument *command) {
// Now block, waiting for a response to be delivered. We assume
// only one thread will be waiting at a time.
nout << "Waiting for response " << response_id << "\n" << flush;
_response_ready.acquire();
while (_response == NULL || _got_response_id != response_id) {
if (_response != NULL) {
@ -307,8 +305,6 @@ command_and_response(TiXmlDocument *command) {
_response_ready.release();
nout << "Got response: " << *response << "\n" << flush;
return response;
}
@ -358,8 +354,6 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
int object_id;
if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
P3D_object *obj = (P3D_object *)object_id;
nout << "Found object " << obj << "\n" << flush;
nout << " formatted is " << *obj << "\n" << flush;
return P3D_OBJECT_COPY(obj);
}
@ -534,8 +528,6 @@ start_p3dpython() {
}
_p3dpython_running = true;
nout << "Created child process\n" << flush;
if (!_pipe_read) {
nout << "unable to open read pipe\n" << flush;
}
@ -597,14 +589,12 @@ join_read_thread() {
////////////////////////////////////////////////////////////////////
void P3DSession::
rt_thread_run() {
nout << "session thread reading.\n" << flush;
while (_read_thread_continue) {
TiXmlDocument *doc = new TiXmlDocument;
_pipe_read >> *doc;
if (!_pipe_read || _pipe_read.eof()) {
// Some error on reading. Abort.
nout << "Error on session reading.\n" << flush;
rt_terminate();
return;
}
@ -622,8 +612,6 @@ rt_thread_run() {
////////////////////////////////////////////////////////////////////
void P3DSession::
rt_handle_request(TiXmlDocument *doc) {
nout << "Session got request: " << *doc << "\n" << flush;
TiXmlElement *xresponse = doc->FirstChildElement("response");
if (xresponse != (TiXmlElement *)NULL) {
int response_id;
@ -649,7 +637,6 @@ rt_handle_request(TiXmlDocument *doc) {
TiXmlElement *xrequest = doc->FirstChildElement("request");
if (xrequest != (TiXmlElement *)NULL) {
nout << "Handling request\n" << flush;
int instance_id;
if (xrequest->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS) {
// Look up the particular instance this is related to.
@ -665,7 +652,6 @@ rt_handle_request(TiXmlDocument *doc) {
}
RELEASE_LOCK(_instances_lock);
}
nout << "done handling request\n" << flush;
}
delete doc;
@ -699,11 +685,7 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
xrequest->Attribute("unique_id", &unique_id);
if (operation != NULL && xobject != NULL) {
nout << "xobject = " << *xobject << "\n" << flush;
P3D_object *object = xml_to_p3dobj(xobject);
nout << "converted to " << object << "\n" << flush;
nout << "object = " << *object << "\n" << flush;
nout << "operation = " << *operation << "\n" << flush;
if (strcmp(operation, "get_property") == 0 && property_name != NULL) {
request = new P3D_request;
request->_request_type = P3D_RT_script;
@ -737,7 +719,7 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
}
} else {
nout << "ignoring request of type " << rtype << "\n";
nout << "Ignoring request of type " << rtype << "\n";
}
}

View File

@ -121,6 +121,12 @@ get_repr(char *buffer, int buffer_length) const {
P3D_object *PPBrowserObject::
get_property(const string &property) const {
NPIdentifier property_name = browser->getstringidentifier(property.c_str());
if (!browser->hasproperty(_instance->get_npp_instance(), _npobj,
property_name)) {
// No such property.
return NULL;
}
NPVariant result;
if (!browser->getproperty(_instance->get_npp_instance(), _npobj,
property_name, &result)) {
@ -142,10 +148,30 @@ get_property(const string &property) const {
////////////////////////////////////////////////////////////////////
bool PPBrowserObject::
set_property(const string &property, P3D_object *value) {
NPIdentifier property_name = browser->getstringidentifier(property.c_str());
bool result;
if (value != NULL) {
// Set the property.
if (P3D_OBJECT_GET_TYPE(value) != P3D_OT_null) {
NPVariant npvalue;
_instance->p3dobj_to_variant(&npvalue, value);
result = browser->setproperty(_instance->get_npp_instance(), _npobj,
property_name, &npvalue);
browser->releasevariantvalue(&npvalue);
} else {
// Actually, delete the property after all.
result = browser->removeproperty(_instance->get_npp_instance(), _npobj,
property_name);
}
P3D_OBJECT_FINISH(value);
} else {
// Delete the property.
result = browser->removeproperty(_instance->get_npp_instance(), _npobj,
property_name);
}
return false;
return result;
}
////////////////////////////////////////////////////////////////////

View File

@ -34,7 +34,6 @@
PPInstance::
PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
logfile << "constructing " << this << "\n" << flush;
_p3d_inst = NULL;
_npp_instance = instance;
@ -47,8 +46,6 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
P3D_token token;
token._keyword = strdup(argn[i]);
token._value = strdup(argv[i]);
logfile
<< " " << i << ": " << token._keyword << " = " << token._value << "\n";
_tokens.push_back(token);
}
@ -72,9 +69,6 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
////////////////////////////////////////////////////////////////////
PPInstance::
~PPInstance() {
logfile
<< "destructing PPInstance " << this << "\n";
#ifdef _WIN32
if (_got_window) {
// Restore the parent window to its own window handler.
@ -330,7 +324,6 @@ stream_as_file(NPStream *stream, const char *fname) {
}
}
filename = fname2;
logfile << "converted filename to " << filename << "\n";
}
// Here's another temporary hack. In addition to the weird filename
@ -343,7 +336,6 @@ stream_as_file(NPStream *stream, const char *fname) {
// the filename to point to the source file.
if (strncmp(stream->url, "file://", 7) == 0) {
filename = stream->url + 7;
logfile << "converted filename again to " << filename << "\n";
}
#endif // __APPLE__
@ -353,7 +345,6 @@ stream_as_file(NPStream *stream, const char *fname) {
case PPDownloadRequest::RT_contents_file:
// Now we have the contents.xml file. Read this to get the
// filename and md5 hash of our core API DLL.
logfile << "got contents file " << filename << "\n" << flush;
if (!read_contents_file(filename)) {
logfile << "Unable to read contents file\n";
// TODO: fail
@ -388,16 +379,12 @@ stream_as_file(NPStream *stream, const char *fname) {
////////////////////////////////////////////////////////////////////
void PPInstance::
handle_request(P3D_request *request) {
logfile
<< "handle_request: " << request << ", " << request->_request_type
<< " within " << this << "\n" << flush;
assert(request->_instance == _p3d_inst);
bool handled = false;
switch (request->_request_type) {
case P3D_RT_stop:
logfile << "Got P3D_RT_stop\n";
if (_p3d_inst != NULL) {
P3D_instance_finish(_p3d_inst);
_p3d_inst = NULL;
@ -408,9 +395,6 @@ handle_request(P3D_request *request) {
case P3D_RT_get_url:
{
logfile << "Got P3D_RT_get_url: " << request->_request._get_url._url
<< "\n";
PPDownloadRequest *req =
new PPDownloadRequest(PPDownloadRequest::RT_user,
request->_request._get_url._unique_id);
@ -421,15 +405,11 @@ handle_request(P3D_request *request) {
case P3D_RT_notify:
{
logfile << "Got P3D_RT_notify: " << request->_request._notify._message
<< "\n" << flush;
if (_script_object != NULL &&
strcmp(request->_request._notify._message, "onpythonload") == 0) {
// Now that Python is running, initialize our script_object
// with the proper P3D object pointer.
P3D_object *obj = P3D_instance_get_panda_script_object(_p3d_inst);
logfile << "late obj = " << obj << "\n" << flush;
_script_object->set_p3d_object(obj);
}
}
@ -477,9 +457,7 @@ handle_request_loop() {
////////////////////////////////////////////////////////////////////
NPObject *PPInstance::
get_panda_script_object() {
logfile << "get_panda_script_object\n" << flush;
if (_script_object != NULL) {
logfile << "returning _script_object ref = " << _script_object->referenceCount << "\n";
return _script_object;
}
@ -487,14 +465,10 @@ get_panda_script_object() {
if (_p3d_inst != NULL) {
obj = P3D_instance_get_panda_script_object(_p3d_inst);
logfile << "obj = " << obj << "\n" << flush;
}
_script_object = PPPandaObject::make_new(this, obj);
logfile << "_script_object ref = " << _script_object->referenceCount << "\n";
browser->retainobject(_script_object);
logfile << "after retain, _script_object ref = " << _script_object->referenceCount << "\n";
logfile << "ppobj = " << _script_object << "\n" << flush;
return _script_object;
}
@ -507,6 +481,10 @@ get_panda_script_object() {
void PPInstance::
p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
switch (P3D_OBJECT_GET_TYPE(object)) {
case P3D_OT_null:
NULL_TO_NPVARIANT(*result);
break;
case P3D_OT_none:
VOID_TO_NPVARIANT(*result);
break;
@ -551,8 +529,9 @@ p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
////////////////////////////////////////////////////////////////////
P3D_object *PPInstance::
variant_to_p3dobj(const NPVariant *variant) {
if (NPVARIANT_IS_VOID(*variant) ||
NPVARIANT_IS_NULL(*variant)) {
if (NPVARIANT_IS_NULL(*variant)) {
return P3D_new_null_object();
} else if (NPVARIANT_IS_VOID(*variant)) {
return P3D_new_none_object();
} else if (NPVARIANT_IS_BOOLEAN(*variant)) {
return P3D_new_bool_object(NPVARIANT_TO_BOOLEAN(*variant));
@ -675,7 +654,6 @@ downloaded_plugin(const string &filename) {
if (_core_api_dll.quick_verify(_root_dir)) {
// We downloaded and installed it successfully. Now load it.
logfile << "Successfully downloaded " << pathname << "\n";
do_load_plugin();
return;
}
@ -711,7 +689,6 @@ do_load_plugin() {
logfile << "Unable to launch core API in " << pathname << "\n" << flush;
return;
}
logfile << "loaded core API from " << pathname << "\n" << flush;
create_instance();
}
@ -750,7 +727,6 @@ create_instance() {
NPObject *window_object = NULL;
if (browser->getvalue(_npp_instance, NPNVWindowNPObject,
&window_object) == NPERR_NO_ERROR) {
logfile << "Got window_object " << window_object << "\n" << flush;
PPBrowserObject *pobj = new PPBrowserObject(this, window_object);
P3D_instance_set_browser_script_object(_p3d_inst, pobj);
browser->releaseobject(window_object);

View File

@ -27,6 +27,7 @@ from direct.stdpy import file
from direct.task.TaskManagerGlobal import taskMgr
from direct.showbase import AppRunnerGlobal
import os
import types
import __builtin__
MultifileRoot = '/mf'
@ -41,10 +42,10 @@ default-model-extension .bam
class ArgumentError(AttributeError):
pass
class ScriptRoot:
class ScriptAttributes:
""" This dummy class serves as the root object for the scripting
interface. The Python code can store objects and functions here
for direct meddling by the browser's JavaScript code. """
for direct inspection by the browser's JavaScript code. """
pass
class AppRunner(DirectObject):
@ -57,15 +58,23 @@ class AppRunner(DirectObject):
self.started = False
self.windowPrc = None
# Store this Null instance where the application can easily
# get to it.
self.Null = Null
# This is per session.
self.nextScriptId = 0
# TODO: we need one of these per instance, not per session.
self.instanceId = None
self.scriptRoot = ScriptRoot()
# This will be the browser's toplevel window DOM object.
self.window = None
# The attributes of this object will be exposed as attributes
# of the plugin instance in the DOM.
self.attributes = ScriptAttributes()
# This will be the browser's toplevel window DOM object;
# e.g. self.dom.document will be the document.
self.dom = None
# This is the default requestFunc that is installed if we
# never call setRequestFunc().
@ -151,13 +160,20 @@ class AppRunner(DirectObject):
if hasattr(main, 'main') and callable(main.main):
main.main()
def setBrowserScriptObject(self, window):
""" Replaces self.window with the browser's toplevel DOM
def getPandaScriptObject(self):
""" Called by the browser to query the Panda instance's
toplevel scripting object, for querying properties in the
Panda instance. The attributes on this object are mapped to
the plugin instance within the DOM. """
return self.attributes
def setBrowserScriptObject(self, dom):
""" Called by the browser to supply the browser's toplevel DOM
object, for controlling the JavaScript and the document in the
same page with the Panda3D plugin. """
self.window = window
print "setBrowserScriptObject(%s)" % (window)
self.dom = dom
print "setBrowserScriptObject(%s)" % (dom)
def setP3DFilename(self, p3dFilename, tokens = [],
instanceId = None):
@ -166,7 +182,7 @@ class AppRunner(DirectObject):
# for this instance.
self.instanceId = instanceId
# Now that we have an instanceId, we can response to queries
# Now that we have an instanceId, we can respond to queries
# and such.
self.sendRequest('notify', 'onpythonload')
@ -266,8 +282,6 @@ class AppRunner(DirectObject):
return self.requestFunc(self.instanceId, request, args)
def windowEvent(self, win):
print "Got window event in runp3d"
self.sendRequest('notify', 'onwindowopen')
def scriptRequest(self, operation, object, propertyName = None,
@ -297,7 +311,6 @@ class AppRunner(DirectObject):
# Now wait for the response to come in.
result = self.sendRequest('wait_script_response', uniqueId)
print "result for %s.%s = %s" % (object, propertyName, result,)
return result
def parseSysArgs(self):
@ -332,6 +345,16 @@ class AppRunner(DirectObject):
return (osFilename, tokens)
class NullObject:
""" This is a special object that is returned by the browser to
represent a NULL pointer, typically the return value for a failed
operation. It has no attributes. """
pass
# In fact, we normally always return this precise instance of the
# NullObject.
Null = NullObject()
class BrowserObject:
""" This class provides the Python wrapper around some object that
actually exists in the plugin host's namespace, e.g. a JavaScript
@ -348,25 +371,27 @@ class BrowserObject:
return True
def __getattr__(self, name):
""" Remaps attempts to query an attribute into the appropriate
calls to query the actual browser object under the hood. """
""" Remaps attempts to query an attribute, as in obj.attr,
into the appropriate calls to query the actual browser object
under the hood. """
print "__getattr_(self, %s)" % (name)
print "runner = %s" % (self.__runner)
value = self.__runner.scriptRequest('get_property', self,
propertyName = name)
if value is Null:
# Failed to retrieve the attribute.
raise AttributeError(name)
return value
# raise AttributeError(name)
def __setattr__(self, name, value):
if name in self.__dict__:
self.__dict__[name] = value
return
value = self.__runner.scriptRequest('set_property', self,
propertyName = name,
value = value)
if not value:
result = self.__runner.scriptRequest('set_property', self,
propertyName = name,
value = value)
if not result:
raise AttributeError(name)
def __delattr__(self, name):
@ -374,11 +399,50 @@ class BrowserObject:
del self.__dict__[name]
return
value = self.__runner.scriptRequest('del_property', self,
propertyName = name)
if not value:
result = self.__runner.scriptRequest('del_property', self,
propertyName = name)
if not result:
raise AttributeError(name)
def __getitem__(self, key):
""" Remaps attempts to query an attribute, as in obj['attr'],
into the appropriate calls to query the actual browser object
under the hood. Following the JavaScript convention, we treat
obj['attr'] almost the same as obj.attr. """
value = self.__runner.scriptRequest('get_property', self,
propertyName = str(key))
if value is Null:
# Failed to retrieve the property. We return IndexError
# for numeric keys so we can properly support Python's
# iterators, but we return KeyError for string keys to
# emulate mapping objects.
if isinstance(key, types.StringTypes):
raise KeyError(key)
else:
raise IndexError(key)
return value;
def __setitem__(self, key, value):
result = self.__runner.scriptRequest('set_property', self,
propertyName = str(key),
value = value)
if not result:
if isinstance(key, types.StringTypes):
raise KeyError(key)
else:
raise IndexError(key)
def __delitem__(self, key):
result = self.__runner.scriptRequest('del_property', self,
propertyName = str(key))
if not result:
if isinstance(key, types.StringTypes):
raise KeyError(key)
else:
raise IndexError(key)
if __name__ == '__main__':
runner = AppRunner()
runner.gotWindow = True