Browse Source

'main' object

David Rose 16 years ago
parent
commit
f34abe4411

+ 2 - 2
direct/src/plugin/Sources.pp

@@ -36,6 +36,7 @@
     p3dInstance.h p3dInstance.I \
     p3dInstanceManager.h p3dInstanceManager.I \
     p3dIntObject.h \
+    p3dMainObject.h \
     p3dMultifileReader.h p3dMultifileReader.I \
     p3dNoneObject.h \
     p3dObject.h p3dObject.I \
@@ -47,7 +48,6 @@
     p3dSplashWindow.h p3dSplashWindow.I \
     p3dStringObject.h \
     p3dTemporaryFile.h p3dTemporaryFile.I \
-    p3dToplevelObject.h \
     p3dUndefinedObject.h \
     p3dWinSplashWindow.h p3dWinSplashWindow.I \
     p3dX11SplashWindow.h \
@@ -67,6 +67,7 @@
     p3dInstance.cxx \
     p3dInstanceManager.cxx \
     p3dIntObject.cxx \
+    p3dMainObject.cxx \
     p3dMultifileReader.cxx \
     p3dNoneObject.cxx \
     p3dObject.cxx \
@@ -78,7 +79,6 @@
     p3dSplashWindow.cxx \
     p3dStringObject.cxx \
     p3dTemporaryFile.cxx \
-    p3dToplevelObject.cxx \
     p3dUndefinedObject.cxx \
     p3dWinSplashWindow.cxx \
     p3dX11SplashWindow.cxx \

+ 11 - 11
direct/src/plugin/fileSpec.cxx

@@ -94,33 +94,33 @@ quick_verify(const string &package_dir) const {
   string pathname = get_pathname(package_dir);
   struct stat st;
   if (stat(pathname.c_str(), &st) != 0) {
-    //nout << "file not found: " << _filename << "\n";
+    //cerr << "file not found: " << _filename << "\n";
     return false;
   }
 
   if (st.st_size != _size) {
     // If the size is wrong, the file fails.
-    //nout << "size wrong: " << _filename << "\n";
+    //cerr << "size wrong: " << _filename << "\n";
     return false;
   }
 
   if (st.st_mtime == _timestamp) {
     // If the size is right and the timestamp is right, the file passes.
-    //nout << "file ok: " << _filename << "\n";
+    //cerr << "file ok: " << _filename << "\n";
     return true;
   }
 
-  //nout << "modification time wrong: " << _filename << "\n";
+  //cerr << "modification time wrong: " << _filename << "\n";
 
   // If the size is right but the timestamp is wrong, the file
   // soft-fails.  We follow this up with a hash check.
   if (!check_hash(pathname)) {
     // Hard fail, the hash is wrong.
-    //nout << "hash check wrong: " << _filename << "\n";
+    //cerr << "hash check wrong: " << _filename << "\n";
     return false;
   }
 
-  //nout << "hash check ok: " << _filename << "\n";
+  //cerr << "hash check ok: " << _filename << "\n";
 
   // The hash is OK after all.  Change the file's timestamp back to
   // what we expect it to be, so we can quick-verify it successfully
@@ -149,13 +149,13 @@ full_verify(const string &package_dir) const {
   string pathname = get_pathname(package_dir);
   struct stat st;
   if (stat(pathname.c_str(), &st) != 0) {
-    //nout << "file not found: " << _filename << "\n";
+    //cerr << "file not found: " << _filename << "\n";
     return false;
   }
 
   if (st.st_size != _size) {
     // If the size is wrong, the file fails.
-    //nout << "size wrong: " << _filename << "\n";
+    //cerr << "size wrong: " << _filename << "\n";
     return false;
   }
 
@@ -163,11 +163,11 @@ full_verify(const string &package_dir) const {
   // soft-fails.  We follow this up with a hash check.
   if (!check_hash(pathname)) {
     // Hard fail, the hash is wrong.
-    //nout << "hash check wrong: " << _filename << "\n";
+    //cerr << "hash check wrong: " << _filename << "\n";
     return false;
   }
 
-  //nout << "hash check ok: " << _filename << "\n";
+  //cerr << "hash check ok: " << _filename << "\n";
 
   // The hash is OK.  If the timestamp is wrong, change it back to
   // what we expect it to be, so we can quick-verify it successfully
@@ -193,7 +193,7 @@ bool FileSpec::
 check_hash(const string &pathname) const {
   ifstream stream(pathname.c_str(), ios::in | ios::binary);
   if (!stream) {
-    //nout << "unable to read " << pathname << "\n";
+    //cerr << "unable to read " << pathname << "\n";
     return false;
   }
 

+ 3 - 3
direct/src/plugin/p3dInstance.cxx

@@ -22,7 +22,7 @@
 #include "p3dOsxSplashWindow.h"
 #include "p3dX11SplashWindow.h"
 #include "p3dObject.h"
-#include "p3dToplevelObject.h"
+#include "p3dMainObject.h"
 #include "p3dUndefinedObject.h"
 #include "p3dMultifileReader.h"
 #include "p3dTemporaryFile.h"
@@ -57,7 +57,7 @@ P3DInstance(P3D_request_ready_func *func,
   _func(func)
 {
   _browser_script_object = NULL;
-  _panda_script_object = new P3DToplevelObject;
+  _panda_script_object = new P3DMainObject;
   _user_data = user_data;
   _request_pending = false;
   _temp_p3d_filename = NULL;
@@ -1011,7 +1011,7 @@ handle_notify_request(const string &message) {
   // to this instance.
   nout << "Got notify: " << message << "\n";
   if (message == "onpythonload") {
-    // Once Python is up and running, we can get the actual toplevel
+    // Once Python is up and running, we can get the actual main
     // object from the Python side, and merge it with our own.
 
     TiXmlDocument *doc = new TiXmlDocument;

+ 2 - 2
direct/src/plugin/p3dInstance.h

@@ -39,7 +39,7 @@ class P3DSplashWindow;
 class P3DDownload;
 class P3DPackage;
 class P3DObject;
-class P3DToplevelObject;
+class P3DMainObject;
 class P3DTemporaryFile;
 
 ////////////////////////////////////////////////////////////////////
@@ -144,7 +144,7 @@ private:
 
   P3D_request_ready_func *_func;
   P3D_object *_browser_script_object;
-  P3DToplevelObject *_panda_script_object;
+  P3DMainObject *_panda_script_object;
 
   P3DTemporaryFile *_temp_p3d_filename;
   P3DTemporaryFile *_temp_splash_image;

+ 1 - 1
direct/src/plugin/p3dInstanceManager.cxx

@@ -49,7 +49,7 @@ P3DInstanceManager *P3DInstanceManager::_global_ptr;
 P3DInstanceManager::
 P3DInstanceManager() {
   _is_initialized = false;
-  _next_temp_filename_counter = 0;
+  _next_temp_filename_counter = 1;
   _unique_id = 0;
 
   _notify_thread_continue = false;

+ 35 - 35
direct/src/plugin/p3dToplevelObject.cxx → direct/src/plugin/p3dMainObject.cxx

@@ -1,4 +1,4 @@
-// Filename: p3dToplevelObject.cxx
+// Filename: p3dMainObject.cxx
 // Created by:  drose (10Jul09)
 //
 ////////////////////////////////////////////////////////////////////
@@ -12,26 +12,26 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#include "p3dToplevelObject.h"
+#include "p3dMainObject.h"
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::Constructor
+//     Function: P3DMainObject::Constructor
 //       Access: Public
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-P3DToplevelObject::
-P3DToplevelObject() :
+P3DMainObject::
+P3DMainObject() :
   _pyobj(NULL)
 {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::Destructor
+//     Function: P3DMainObject::Destructor
 //       Access: Public, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-P3DToplevelObject::
-~P3DToplevelObject() {
+P3DMainObject::
+~P3DMainObject() {
   set_pyobj(NULL);
 
   // Clear the local properties.
@@ -44,58 +44,58 @@ P3DToplevelObject::
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::get_type
+//     Function: P3DMainObject::get_type
 //       Access: Public, Virtual
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
-P3D_object_type P3DToplevelObject::
+P3D_object_type P3DMainObject::
 get_type() {
   return P3D_OT_object;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::get_bool
+//     Function: P3DMainObject::get_bool
 //       Access: Public, Virtual
 //  Description: Returns the object value coerced to a boolean, if
 //               possible.
 ////////////////////////////////////////////////////////////////////
-bool P3DToplevelObject::
+bool P3DMainObject::
 get_bool() {
   return true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::get_int
+//     Function: P3DMainObject::get_int
 //       Access: Public, Virtual
 //  Description: Returns the object value coerced to an integer, if
 //               possible.
 ////////////////////////////////////////////////////////////////////
-int P3DToplevelObject::
+int P3DMainObject::
 get_int() {
   return 0;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::get_float
+//     Function: P3DMainObject::get_float
 //       Access: Public, Virtual
 //  Description: Returns the object value coerced to a floating-point
 //               value, if possible.
 ////////////////////////////////////////////////////////////////////
-double P3DToplevelObject::
+double P3DMainObject::
 get_float() {
   return 0.0;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::make_string
+//     Function: P3DMainObject::make_string
 //       Access: Public, Virtual
 //  Description: Fills the indicated C++ string object with the value
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
-void P3DToplevelObject::
+void P3DMainObject::
 make_string(string &value) {
   if (_pyobj == NULL) {
-    value = "P3DToplevelObject";
+    value = "P3DMainObject";
   } else {
     int size = P3D_OBJECT_GET_STRING(_pyobj, NULL, 0);
     char *buffer = new char[size];
@@ -106,13 +106,13 @@ make_string(string &value) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::get_property
+//     Function: P3DMainObject::get_property
 //       Access: Public, Virtual
 //  Description: Returns the named property element in the object.  The
 //               return value is a new-reference P3D_object, or NULL
 //               on error.
 ////////////////////////////////////////////////////////////////////
-P3D_object *P3DToplevelObject::
+P3D_object *P3DMainObject::
 get_property(const string &property) {
   if (_pyobj == NULL) {
     // Without a pyobj, we just report whatever's been stored locally.
@@ -131,13 +131,13 @@ get_property(const string &property) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::set_property
+//     Function: P3DMainObject::set_property
 //       Access: Public, Virtual
 //  Description: Modifies (or deletes, if value is NULL) the named
 //               property element in the object.  Returns true on
 //               success, false on failure.
 ////////////////////////////////////////////////////////////////////
-bool P3DToplevelObject::
+bool P3DMainObject::
 set_property(const string &property, P3D_object *value) {
   // First, we set the property locally.
   if (value != NULL) {
@@ -171,12 +171,12 @@ set_property(const string &property, P3D_object *value) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::has_method
+//     Function: P3DMainObject::has_method
 //       Access: Public, Virtual
 //  Description: Returns true if the named method exists on this
 //               object, false otherwise.
 ////////////////////////////////////////////////////////////////////
-bool P3DToplevelObject::
+bool P3DMainObject::
 has_method(const string &method_name) {
   if (_pyobj == NULL) {
     // No methods until we get our pyobj.
@@ -187,7 +187,7 @@ has_method(const string &method_name) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::call
+//     Function: P3DMainObject::call
 //       Access: Public, Virtual
 //  Description: Invokes the named method on the object, passing the
 //               indicated parameters.  If the method name is empty,
@@ -199,7 +199,7 @@ has_method(const string &method_name) {
 //               value is always NULL, and there is no way to
 //               determine success or failure.
 ////////////////////////////////////////////////////////////////////
-P3D_object *P3DToplevelObject::
+P3D_object *P3DMainObject::
 call(const string &method_name, bool needs_response,
      P3D_object *params[], int num_params) {
   if (_pyobj == NULL) {
@@ -212,28 +212,28 @@ call(const string &method_name, bool needs_response,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::output
+//     Function: P3DMainObject::output
 //       Access: Public, Virtual
 //  Description: Writes a formatted representation of the value to the
 //               indicated string.  This is intended for developer
 //               assistance.
 ////////////////////////////////////////////////////////////////////
-void P3DToplevelObject::
+void P3DMainObject::
 output(ostream &out) {
-  out << "P3DToplevelObject";
+  out << "P3DMainObject";
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::set_pyobj
+//     Function: P3DMainObject::set_pyobj
 //       Access: Public
 //  Description: Changes the internal pyobj pointer.  This is the
 //               P3D_object that references the actual PyObject held
 //               within the child process, corresponding to the true
-//               toplevel object there.  The new object's reference
+//               main object there.  The new object's reference
 //               count is incremented, and the previous object's is
 //               decremented.
 ////////////////////////////////////////////////////////////////////
-void P3DToplevelObject::
+void P3DMainObject::
 set_pyobj(P3D_object *pyobj) {
   if (_pyobj != pyobj) {
     P3D_OBJECT_XDECREF(_pyobj);
@@ -254,12 +254,12 @@ set_pyobj(P3D_object *pyobj) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DToplevelObject::get_pyobj
+//     Function: P3DMainObject::get_pyobj
 //       Access: Public
 //  Description: Returns the internal pyobj pointer, or NULL if it has
 //               not yet been set.
 ////////////////////////////////////////////////////////////////////
-P3D_object *P3DToplevelObject::
+P3D_object *P3DMainObject::
 get_pyobj() const {
   return _pyobj;
 }

+ 13 - 10
direct/src/plugin/p3dToplevelObject.h → direct/src/plugin/p3dMainObject.h

@@ -1,4 +1,4 @@
-// Filename: p3dToplevelObject.h
+// Filename: p3dMainObject.h
 // Created by:  drose (10Jul09)
 //
 ////////////////////////////////////////////////////////////////////
@@ -12,8 +12,8 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef P3DTOPLEVELOBJECT_H
-#define P3DTOPLEVELOBJECT_H
+#ifndef P3DMAINOBJECT_H
+#define P3DMAINOBJECT_H
 
 #include "p3d_plugin_common.h"
 #include "p3dObject.h"
@@ -22,10 +22,13 @@
 class P3DSession;
 
 ////////////////////////////////////////////////////////////////////
-//       Class : P3DToplevelObject
-// Description : This corresponds to the toplevel "Python" object
-//               owned by a particular instance, as returned by
-//               P3DInstance::get_panda_script_object().
+//       Class : P3DMainObject
+// Description : This corresponds to the "main" object exposed by a
+//               particular instance, as returned by
+//               P3DInstance::get_panda_script_object().  This object
+//               corresponds to the appRunner.main object in Python,
+//               and the document.pluginobject.main object in
+//               JavaScript.
 //
 //               This is mostly a wrapper around a P3DPythonObject
 //               pointer, and therefore functions like any other
@@ -35,10 +38,10 @@ class P3DSession;
 //               generated directly by the core API (like
 //               downloadProgress and such).
 ////////////////////////////////////////////////////////////////////
-class P3DToplevelObject : public P3DObject {
+class P3DMainObject : public P3DObject {
 public:
-  P3DToplevelObject();
-  virtual ~P3DToplevelObject();
+  P3DMainObject();
+  virtual ~P3DMainObject();
 
 public:
   virtual P3D_object_type get_type();

+ 8 - 3
direct/src/plugin/p3dPackage.cxx

@@ -330,14 +330,19 @@ got_desc_file(TiXmlDocument *doc, bool freshly_downloaded) {
     extract = extract->NextSiblingElement("extract");
   }
 
-  // Verify all of the extracts.
+  // Verify the uncompressed archive.
   bool all_extracts_ok = true;
+  if (!_uncompressed_archive.quick_verify(_package_dir)) {
+    nout << "File is incorrect: " << _uncompressed_archive.get_filename() << "\n";
+    all_extracts_ok = false;
+  }
+
+  // Verify all of the extracts.
   Extracts::iterator ci;
-  for (ci = _extracts.begin(); ci != _extracts.end(); ++ci) {
+  for (ci = _extracts.begin(); ci != _extracts.end() && all_extracts_ok; ++ci) {
     if (!(*ci).quick_verify(_package_dir)) {
       nout << "File is incorrect: " << (*ci).get_filename() << "\n";
       all_extracts_ok = false;
-      break;
     }
   }
 

+ 1 - 1
direct/src/plugin/p3d_plugin_composite1.cxx

@@ -22,7 +22,7 @@
 #include "p3dSplashWindow.cxx"
 #include "p3dStringObject.cxx"
 #include "p3dTemporaryFile.cxx"
-#include "p3dToplevelObject.cxx"
+#include "p3dMainObject.cxx"
 #include "p3dUndefinedObject.cxx"
 #include "p3dWinSplashWindow.cxx"
 #include "p3dX11SplashWindow.cxx"

+ 2 - 0
direct/src/plugin_npapi/Sources.pp

@@ -21,6 +21,7 @@
     ppDownloadRequest.h ppDownloadRequest.I \
     ppInstance.h ppInstance.I \
     ppPandaObject.h ppPandaObject.I \
+    ppToplevelObject.h ppToplevelObject.I \
     startup.h
 
   #define INCLUDED_SOURCES \
@@ -28,6 +29,7 @@
     ppDownloadRequest.cxx \
     ppInstance.cxx \
     ppPandaObject.cxx \
+    ppToplevelObject.cxx \
     startup.cxx
  
   // Windows-specific options.

+ 1 - 0
direct/src/plugin_npapi/nppanda3d_composite1.cxx

@@ -2,6 +2,7 @@
 #include "ppDownloadRequest.cxx"
 #include "ppInstance.cxx"
 #include "ppPandaObject.cxx"
+#include "ppToplevelObject.cxx"
 #include "startup.cxx"
 
 

+ 2 - 1
direct/src/plugin_npapi/ppDownloadRequest.h

@@ -28,7 +28,8 @@ public:
   enum RequestType {
     RT_contents_file,
     RT_core_dll,
-    RT_user
+    RT_user,
+    RT_instance_data
   };
 
   inline PPDownloadRequest(RequestType rtype, int user_id = 0);

+ 34 - 11
direct/src/plugin_npapi/ppInstance.cxx

@@ -14,6 +14,7 @@
 
 #include "ppInstance.h"
 #include "ppPandaObject.h"
+#include "ppToplevelObject.h"
 #include "ppBrowserObject.h"
 #include "startup.h"
 #include "p3d_plugin_config.h"
@@ -73,7 +74,6 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
 ////////////////////////////////////////////////////////////////////
 PPInstance::
 ~PPInstance() {
-  nout << "Destructing PPInstance\n";
   cleanup_window();
 
   if (_p3d_inst != NULL) {
@@ -187,7 +187,17 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
       _instance_url = stream->url;
       if (_p3d_inst != NULL) {
         P3D_instance_start(_p3d_inst, false, _instance_url.c_str());
-      }
+      } 
+
+      // We don't want the rest of this stream any more, but we can't
+      // just return NPERR_GENERIC_ERROR, though--that seems to freak
+      // out Mozilla.  Instead, we'll "accept" it for now, and then
+      // immediately stop it when we get the first write_stream()
+      // call.
+      stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_instance_data);
+
+      *stype = NP_NORMAL;
+      return NPERR_NO_ERROR;
     }
 
     // Don't finish downloading the unsolicited stream.
@@ -232,6 +242,7 @@ int PPInstance::
 write_stream(NPStream *stream, int offset, int len, void *buffer) {
   if (stream->notifyData == NULL) {
     nout << "Unexpected write_stream on " << stream->url << "\n";
+    browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
     return 0;
   }
 
@@ -242,12 +253,18 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
                                  P3D_RC_in_progress, 0,
                                  stream->end, buffer, len);
     return len;
+
+  case PPDownloadRequest::RT_instance_data:
+    // Here's a stream we don't really want.
+    browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
+    return 0;
     
   default:
     nout << "Unexpected write_stream on " << stream->url << "\n";
     break;
   }
 
+  browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
   return 0;
 }
 
@@ -262,7 +279,7 @@ NPError PPInstance::
 destroy_stream(NPStream *stream, NPReason reason) {
   if (stream->notifyData == NULL) {
     nout << "Unexpected destroy_stream on " << stream->url << "\n";
-    return NPERR_GENERIC_ERROR;
+    return NPERR_NO_ERROR;
   }
 
   PPDownloadRequest *req = (PPDownloadRequest *)(stream->notifyData);
@@ -280,10 +297,16 @@ destroy_stream(NPStream *stream, NPReason reason) {
     }
     break;
 
+  case PPDownloadRequest::RT_instance_data:
+    // We won't get a url_notify on this one, so delete it now.
+    delete req;
+    break;
+
   default:
+    nout << "Unexpected destroy_stream on " << stream->url << "\n";
     break;
   }
-  
+
   return NPERR_NO_ERROR;
 }
 
@@ -333,6 +356,7 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
     break;
     
   default:
+    nout << "Unexpected url_notify on stream type " << req->_rtype << "\n";
     break;
   }
   
@@ -539,13 +563,14 @@ get_panda_script_object() {
     return _script_object;
   }
 
-  P3D_object *obj = NULL;
+  P3D_object *main = NULL;
 
   if (_p3d_inst != NULL) {
-    obj = P3D_instance_get_panda_script_object(_p3d_inst);
+    main = P3D_instance_get_panda_script_object(_p3d_inst);
   }
 
-  _script_object = PPPandaObject::make_new(this, obj);
+  _script_object = PPToplevelObject::make_new(this);
+  _script_object->set_main(main);
 
   browser->retainobject(_script_object);
   return _script_object;
@@ -975,8 +1000,8 @@ create_instance() {
     if (_script_object != NULL) {
       // Now that we have a true instance, initialize our
       // script_object with the proper P3D_object pointer.
-      P3D_object *obj = P3D_instance_get_panda_script_object(_p3d_inst);
-      _script_object->set_p3d_object(obj);
+      P3D_object *main = P3D_instance_get_panda_script_object(_p3d_inst);
+      _script_object->set_main(main);
     }
 
     if (_got_instance_url) {
@@ -1069,7 +1094,6 @@ send_window() {
     // No size: hidden.
     window_type = P3D_WT_hidden;
   }    
-  nout << "window_type = " << window_type << "\n";
 
   P3D_instance_setup_window
     (_p3d_inst, window_type,
@@ -1090,7 +1114,6 @@ cleanup_window() {
     // Restore the parent window to its own window handler.
     HWND hwnd = (HWND)_window.window;
     SetWindowLongPtr(hwnd, GWL_WNDPROC, _orig_window_proc);
-    nout << "Restored window handler for " << hwnd << "\n";
     InvalidateRect(hwnd, NULL, true);
 #endif  // _WIN32
     _got_window = false;

+ 2 - 2
direct/src/plugin_npapi/ppInstance.h

@@ -22,7 +22,7 @@
 
 #include <vector>
 
-class PPPandaObject;
+class PPToplevelObject;
 class PPDownloadRequest;
 
 ////////////////////////////////////////////////////////////////////
@@ -140,7 +140,7 @@ private:
 
   bool _python_window_open;
 
-  PPPandaObject *_script_object;
+  PPToplevelObject *_script_object;
 
   P3D_instance *_p3d_inst;
 };

+ 14 - 0
direct/src/plugin_npapi/ppToplevelObject.I

@@ -0,0 +1,14 @@
+// Filename: ppToplevelObject.I
+// Created by:  drose (21Aug09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+

+ 276 - 0
direct/src/plugin_npapi/ppToplevelObject.cxx

@@ -0,0 +1,276 @@
+// Filename: ppToplevelObject.cxx
+// Created by:  drose (21Aug09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "ppToplevelObject.h"
+
+NPClass PPToplevelObject::_object_class = {
+  NP_CLASS_STRUCT_VERSION,
+  &PPToplevelObject::NPAllocate,
+  &PPToplevelObject::NPDeallocate,
+  &PPToplevelObject::NPInvalidate,
+  &PPToplevelObject::NPHasMethod,
+  &PPToplevelObject::NPInvoke,
+  &PPToplevelObject::NPInvokeDefault,
+  &PPToplevelObject::NPHasProperty,
+  &PPToplevelObject::NPGetProperty,
+  &PPToplevelObject::NPSetProperty,
+  &PPToplevelObject::NPRemoveProperty,
+#if defined(NP_CLASS_STRUCT_VERSION_ENUM) && NP_CLASS_STRUCT_VERSION >= NP_CLASS_STRUCT_VERSION_ENUM
+  &PPToplevelObject::NPEnumerate,
+#endif
+#if defined(NP_CLASS_STRUCT_VERSION_CTOR) && NP_CLASS_STRUCT_VERSION >= NP_CLASS_STRUCT_VERSION_CTOR
+  &PPToplevelObject::NPConstruct,
+#endif
+};
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::make_new
+//       Access: Public, Static
+//  Description: Use this call to construct a new PPToplevelObject.
+////////////////////////////////////////////////////////////////////
+PPToplevelObject *PPToplevelObject::
+make_new(PPInstance *inst) {
+  NPObject *npobj = 
+    browser->createobject(inst->get_npp_instance(), &_object_class);
+  PPToplevelObject *ppobj = (PPToplevelObject *)npobj;
+  ppobj->construct(inst);
+  return ppobj;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::set_main
+//       Access: Public
+//  Description: Changes the "main" object this PPToplevelObject maps
+//               to.  The new object's reference count is incremented,
+//               and the previous object's is decremented.
+////////////////////////////////////////////////////////////////////
+void PPToplevelObject::
+set_main(P3D_object *p3d_object) {
+  if (p3d_object != NULL) {
+    P3D_OBJECT_INCREF(p3d_object);
+  }
+  P3D_OBJECT_XDECREF(_main);
+  _main = p3d_object;
+}
+ 
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::construct
+//       Access: Private
+//  Description: Stands in for the C++ constructor.  We can't have a
+//               true constructor because of the C-style interface in
+//               NPN_CreateObject().  This must be called explicitly
+//               following NPN_CreateObject().
+////////////////////////////////////////////////////////////////////
+void PPToplevelObject::
+construct(PPInstance *inst) {
+  _instance = inst;
+  _main = NULL;
+
+  // Get our one property name as an identifier, so we can look for
+  // it.
+  _main_id = browser->getstringidentifier("main");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::invalidate
+//       Access: Private
+//  Description: This "destructor" is called by NPInvalidate().
+////////////////////////////////////////////////////////////////////
+void PPToplevelObject::
+invalidate() {
+  _instance = NULL;
+  set_main(NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::has_property
+//       Access: Private
+//  Description: Returns true if the object has the named property,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+has_property(NPIdentifier name) {
+  if (_main == NULL) {
+    // Not powered up yet.
+    return false;
+  }
+
+  if (name == _main_id) {
+    return true;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::get_property
+//       Access: Private
+//  Description: Retrieves the named property value from the object
+//               and stores it in result.  Returns true on success,
+//               false on failure.
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+get_property(NPIdentifier name, NPVariant *result) {
+  if (_main == NULL) {
+    // Not powered up yet.
+    return false;
+  }
+
+  if (name == _main_id) {
+    _instance->p3dobj_to_variant(result, _main);
+    return true;
+  }
+
+  return false;
+}
+
+
+// The remaining function bodies are the C-style function wrappers
+// that are called directly by NPAPI, and which redirect into the
+// above C++-style methods.
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPAllocate
+//       Access: Private, Static
+//  Description: Called by NPN_CreateObject() to allocate space for
+//               this object.
+////////////////////////////////////////////////////////////////////
+NPObject *PPToplevelObject::
+NPAllocate(NPP npp, NPClass *aClass) {
+  assert(aClass == &_object_class);
+  return (PPToplevelObject *)malloc(sizeof(PPToplevelObject));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::Deallocate
+//       Access: Private, Static
+//  Description: Called to delete the space allocated by NPAllocate,
+//               above.
+////////////////////////////////////////////////////////////////////
+void PPToplevelObject::
+NPDeallocate(NPObject *npobj) {
+  ((PPToplevelObject *)npobj)->invalidate();
+  free(npobj);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::Deallocate
+//       Access: Private, Static
+//  Description: Called to destruct the object.
+////////////////////////////////////////////////////////////////////
+void PPToplevelObject::
+NPInvalidate(NPObject *npobj) {
+  // It turns out that this method isn't actually called by Safari's
+  // implementation of NPAPI, so we'll move the actual destructor call
+  // into NPDeallocate, above.
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPHasMethod
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPHasMethod(NPObject *npobj, NPIdentifier name) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPInvoke
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPInvoke(NPObject *npobj, NPIdentifier name,
+         const NPVariant *args, uint32_t argCount,
+         NPVariant *result) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPInvokeDefault
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPInvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount,
+                NPVariant *result) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPHasProperty
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPHasProperty(NPObject *npobj, NPIdentifier name) {
+  return ((PPToplevelObject *)npobj)->has_property(name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPGetProperty
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) {
+  return ((PPToplevelObject *)npobj)->get_property(name, result);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPSetProperty
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPRemoveProperty
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPRemoveProperty(NPObject *npobj, NPIdentifier name) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPEnumerate
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count) {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPToplevelObject::NPConstruct
+//       Access: Private, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool PPToplevelObject::
+NPConstruct(NPObject *npobj, const NPVariant *args,
+            uint32_t argCount, NPVariant *result) {
+  // Not implemented.  We don't use this constructor mechanism because
+  // it wasn't supported on earlier versions of Gecko.  Instead, we
+  // use make_new() to construct PPToplevelObjects via an explicit call to
+  // construct().
+  return true;
+}

+ 80 - 0
direct/src/plugin_npapi/ppToplevelObject.h

@@ -0,0 +1,80 @@
+// Filename: ppToplevelObject.h
+// Created by:  drose (21Aug09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PPTOPLEVELOBJECT_H
+#define PPTOPLEVELOBJECT_H
+
+#include "nppanda3d_common.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PPToplevelObject
+// Description : This is a special object fed to Mozilla as the
+//               toplevel scripting object for the instance.  It has
+//               only one property, "main", which corresponds to the
+//               appRunner.main object from Python.
+////////////////////////////////////////////////////////////////////
+class PPToplevelObject : public NPObject {
+public:
+  static PPToplevelObject *make_new(PPInstance *inst);
+
+  inline P3D_object *get_main() const;
+  void set_main(P3D_object *main);
+
+private:
+  void construct(PPInstance *inst);
+  void invalidate();
+
+  bool has_property(NPIdentifier name);
+  bool get_property(NPIdentifier name,
+                    NPVariant *result);
+
+private:
+  static NPObject *NPAllocate(NPP npp, NPClass *aClass);
+  static void NPDeallocate(NPObject *npobj);
+  static void NPInvalidate(NPObject *npobj);
+  static bool NPHasMethod(NPObject *npobj, NPIdentifier name);
+  static bool NPInvoke(NPObject *npobj, NPIdentifier name,
+                       const NPVariant *args, uint32_t argCount,
+                       NPVariant *result);
+  static bool NPInvokeDefault(NPObject *npobj,
+                              const NPVariant *args,
+                              uint32_t argCount,
+                              NPVariant *result);
+  static bool NPHasProperty(NPObject *npobj, NPIdentifier name);
+  static bool NPGetProperty(NPObject *npobj, NPIdentifier name,
+                            NPVariant *result);
+  static bool NPSetProperty(NPObject *npobj, NPIdentifier name,
+                            const NPVariant *value);
+  static bool NPRemoveProperty(NPObject *npobj,
+                               NPIdentifier name);
+  static bool NPEnumerate(NPObject *npobj, NPIdentifier **value,
+                          uint32_t *count);
+  static bool NPConstruct(NPObject *npobj,
+                          const NPVariant *args,
+                          uint32_t argCount,
+                          NPVariant *result);
+
+private:
+  PPInstance *_instance;
+  P3D_object *_main;
+  NPIdentifier _main_id;
+
+public:
+  static NPClass _object_class;
+};
+
+#include "ppToplevelObject.I"
+
+#endif
+