Browse Source

further fixes for npapi under unicode directories

David Rose 14 years ago
parent
commit
cbc1842899

+ 244 - 118
direct/src/plugin_npapi/ppInstance.cxx

@@ -18,7 +18,6 @@
 #include "ppBrowserObject.h"
 #include "ppBrowserObject.h"
 #include "startup.h"
 #include "startup.h"
 #include "p3d_plugin_config.h"
 #include "p3d_plugin_config.h"
-#include "find_root_dir.h"
 #include "mkdir_complete.h"
 #include "mkdir_complete.h"
 #include "parse_color.h"
 #include "parse_color.h"
 #include "nppanda3d_common.h"
 #include "nppanda3d_common.h"
@@ -97,10 +96,6 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode,
   _root_dir = global_root_dir;
   _root_dir = global_root_dir;
 
 
   _got_instance_url = false;
   _got_instance_url = false;
-  _opened_p3d_temp_file = false;
-  _finished_p3d_temp_file = false;
-  _p3d_temp_file_current_size = 0;
-  _p3d_temp_file_total_size = 0;
   _p3d_instance_id = 0;
   _p3d_instance_id = 0;
 
 
   // fgcolor and bgcolor are useful to know here (in case we have to
   // fgcolor and bgcolor are useful to know here (in case we have to
@@ -216,12 +211,6 @@ PPInstance::
     browser->releaseobject(_script_object);
     browser->releaseobject(_script_object);
   }
   }
 
 
-  if (!_p3d_temp_filename.empty()) {
-    _p3d_temp_file.close();
-    unlink(_p3d_temp_filename.c_str());
-    _p3d_temp_filename.clear();
-  }
-
   // Free the tokens we allocated.
   // Free the tokens we allocated.
   Tokens::iterator ti;
   Tokens::iterator ti;
   for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
   for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
@@ -412,16 +401,17 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16_t *stype) {
   PPDownloadRequest *req = (PPDownloadRequest *)(stream->notifyData);
   PPDownloadRequest *req = (PPDownloadRequest *)(stream->notifyData);
   switch (req->_rtype) {
   switch (req->_rtype) {
   case PPDownloadRequest::RT_contents_file:
   case PPDownloadRequest::RT_contents_file:
-    // This is the initial contents.xml file.  We'll just download
-    // this directly to a file, since it is small and this is easy.
-    *stype = NP_ASFILEONLY;
+    // This is the initial contents.xml file.  We used to download
+    // this via NP_ASFILEONLY, but that option doesn't work on Windows
+    // within a Unicode user directory.  So we use NP_NORMAL instead.
+    *stype = NP_NORMAL;
     _streams.push_back(stream);
     _streams.push_back(stream);
     return NPERR_NO_ERROR;
     return NPERR_NO_ERROR;
 
 
   case PPDownloadRequest::RT_core_dll:
   case PPDownloadRequest::RT_core_dll:
-    // This is the core API DLL (or dylib or whatever).  We want to
-    // download this to file for convenience.
-    *stype = NP_ASFILEONLY;
+    // This is the core API DLL (or dylib or whatever).  Again, we
+    // have to use NP_NORMAL.
+    *stype = NP_NORMAL;
     _streams.push_back(stream);
     _streams.push_back(stream);
     return NPERR_NO_ERROR;
     return NPERR_NO_ERROR;
 
 
@@ -510,8 +500,8 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
   switch (req->_rtype) {
   switch (req->_rtype) {
   case PPDownloadRequest::RT_user:
   case PPDownloadRequest::RT_user:
     P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
     P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
-                                 P3D_RC_in_progress, 0,
-                                 stream->end, buffer, len);
+                                     P3D_RC_in_progress, 0,
+                                     stream->end, buffer, len);
     return len;
     return len;
 
 
   case PPDownloadRequest::RT_instance_data:
   case PPDownloadRequest::RT_instance_data:
@@ -533,26 +523,35 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
     // temporary file until the instance is ready for it.
     // temporary file until the instance is ready for it.
     if (_p3d_inst == NULL) {
     if (_p3d_inst == NULL) {
       // The instance isn't ready, so stuff it in a temporary file.
       // The instance isn't ready, so stuff it in a temporary file.
-      if (!_opened_p3d_temp_file) {
-        open_p3d_temp_file();
+      if (!_p3d_temp_file.feed(stream->end, buffer, len)) {
+        set_failed();
       }
       }
-      _p3d_temp_file.write((const char *)buffer, len);
-      _p3d_temp_file_current_size += len;
-      _p3d_temp_file_total_size = stream->end;
       return len;
       return len;
 
 
     } else {
     } else {
       // The instance has been created.  Redirect the stream into the
       // The instance has been created.  Redirect the stream into the
       // instance.
       // instance.
-      assert(!_opened_p3d_temp_file);
+      assert(!_p3d_temp_file._opened);
       req->_rtype = PPDownloadRequest::RT_user;
       req->_rtype = PPDownloadRequest::RT_user;
       req->_user_id = _p3d_instance_id;
       req->_user_id = _p3d_instance_id;
       P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
       P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
-                                   P3D_RC_in_progress, 0,
-                                   stream->end, buffer, len);
+                                       P3D_RC_in_progress, 0,
+                                       stream->end, buffer, len);
       return len;
       return len;
     }
     }
     break;
     break;
+
+  case PPDownloadRequest::RT_contents_file:
+    if (!_contents_temp_file.feed(stream->end, buffer, len)) {
+      set_failed();
+    }
+    return len;
+
+  case PPDownloadRequest::RT_core_dll:
+    if (!_core_dll_temp_file.feed(stream->end, buffer, len)) {
+      set_failed();
+    }
+    return len;
     
     
   default:
   default:
     nout << "Unexpected write_stream on " << stream->url << "\n";
     nout << "Unexpected write_stream on " << stream->url << "\n";
@@ -595,38 +594,51 @@ destroy_stream(NPStream *stream, NPReason reason) {
 
 
   switch (req->_rtype) {
   switch (req->_rtype) {
   case PPDownloadRequest::RT_user:
   case PPDownloadRequest::RT_user:
-    {
-      assert(!req->_notified_done);
+    if (!req->_notified_done) {
       P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
       P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
-                                   result_code, 0, stream->end, NULL, 0);
+                                       result_code, 0, stream->end, NULL, 0);
       req->_notified_done = true;
       req->_notified_done = true;
     }
     }
     break;
     break;
 
 
   case PPDownloadRequest::RT_instance_data:
   case PPDownloadRequest::RT_instance_data:
-    if (_p3d_inst == NULL) {
-      // The instance still isn't ready; just mark the data done.
-      // We'll send the entire file to the instance when it is ready.
-      _finished_p3d_temp_file = true;
-      _p3d_temp_file_total_size = _p3d_temp_file_current_size;
+    if (!req->_notified_done) {
+      if (_p3d_inst == NULL) {
+        // The instance still isn't ready; just mark the data done.
+        // We'll send the entire file to the instance when it is ready.
+        _p3d_temp_file.finish();
+        if (result_code != P3D_RC_done) {
+          set_failed();
+        }
+        
+      } else {
+        // The instance has (only just) been created.  Tell it we've
+        // sent it all the data it will get.
+        P3D_instance_feed_url_stream_ptr(_p3d_inst, _p3d_instance_id,
+                                         result_code, 0, stream->end, NULL, 0);
+      }
+      req->_notified_done = true;
+    }
+    break;
+
+  case PPDownloadRequest::RT_contents_file:
+    if (!req->_notified_done) {
+      _contents_temp_file.finish();
       if (result_code != P3D_RC_done) {
       if (result_code != P3D_RC_done) {
         set_failed();
         set_failed();
       }
       }
-
-    } else {
-      // The instance has (only just) been created.  Tell it we've
-      // sent it all the data it will get.
-      P3D_instance_feed_url_stream_ptr(_p3d_inst, _p3d_instance_id,
-                                   result_code, 0, stream->end, NULL, 0);
+      req->_notified_done = true;
     }
     }
-    assert(!req->_notified_done);
-    req->_notified_done = true;
     break;
     break;
 
 
   case PPDownloadRequest::RT_core_dll:
   case PPDownloadRequest::RT_core_dll:
-  case PPDownloadRequest::RT_contents_file:
-    // These are received as a full-file only, so we don't care about
-    // the destroy_stream notification.
+    if (!req->_notified_done) {
+      _core_dll_temp_file.finish();
+      if (result_code != P3D_RC_done) {
+        set_failed();
+      }
+      req->_notified_done = true;
+    }
     break;
     break;
 
 
   default:
   default:
@@ -668,13 +680,15 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
       assert(reason != NPRES_DONE);
       assert(reason != NPRES_DONE);
 
 
       P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
       P3D_instance_feed_url_stream_ptr(_p3d_inst, req->_user_id,
-                                   P3D_RC_generic_error, 0, 0, NULL, 0);
+                                       P3D_RC_generic_error, 0, 0, NULL, 0);
       req->_notified_done = true;
       req->_notified_done = true;
     }
     }
     break;
     break;
 
 
   case PPDownloadRequest::RT_contents_file:
   case PPDownloadRequest::RT_contents_file:
-    if (reason != NPRES_DONE) {
+    if (reason == NPRES_DONE) {
+      downloaded_contents_file(_contents_temp_file._filename);
+    } else {
       nout << "Failure downloading " << url << "\n";
       nout << "Failure downloading " << url << "\n";
 
 
       if (reason == NPRES_USER_BREAK) {
       if (reason == NPRES_USER_BREAK) {
@@ -695,7 +709,10 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
     break;
     break;
     
     
   case PPDownloadRequest::RT_core_dll:
   case PPDownloadRequest::RT_core_dll:
-    if (reason != NPRES_DONE) {
+    if (reason == NPRES_DONE) {
+      downloaded_plugin(_core_dll_temp_file._filename);
+
+    } else {
       nout << "Failure downloading " << url << "\n";
       nout << "Failure downloading " << url << "\n";
 
 
       if (reason == NPRES_USER_BREAK) {
       if (reason == NPRES_USER_BREAK) {
@@ -1269,6 +1286,38 @@ start_download(const string &url, PPDownloadRequest *req) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::downloaded_contents_file
+//       Access: Private
+//  Description: The contents.xml file has been successfully downloaded;
+//               copy it into place.
+////////////////////////////////////////////////////////////////////
+void PPInstance::
+downloaded_contents_file(const string &filename) {
+  // Now we have the contents.xml file.  Read this to get the
+  // filename and md5 hash of our core API DLL.
+  if (read_contents_file(filename, true)) {
+    // Successfully downloaded and read, and it has been written
+    // into its normal place.
+    get_core_api();
+    
+  } else {
+    // Error reading the contents.xml file, or in loading the core
+    // API that it references.
+    nout << "Unable to read contents file " << filename << "\n";
+    
+    // If there's an outstanding contents.xml file on disk, try to
+    // load that one as a fallback.
+    string contents_filename = _root_dir + "/contents.xml";
+    if (read_contents_file(contents_filename, false)) {
+      get_core_api();
+    } else {
+      nout << "Unable to read contents file " << contents_filename << "\n";
+      set_failed();
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PPInstance::read_contents_file
 //     Function: PPInstance::read_contents_file
 //       Access: Private
 //       Access: Private
@@ -1428,32 +1477,14 @@ get_filename_from_url(const string &url) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PPInstance::
 void PPInstance::
 downloaded_file(PPDownloadRequest *req, const string &filename) {
 downloaded_file(PPDownloadRequest *req, const string &filename) {
+  // Since we're no longer using NP_ASFILEONLY, none of these URL
+  // requests will normally come through this codepath (they'll go
+  // through url_notify() above, instead), unless we short-circuited
+  // the browser by "downloading" a file:// url.
   switch (req->_rtype) {
   switch (req->_rtype) {
   case PPDownloadRequest::RT_contents_file:
   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.
-      if (read_contents_file(filename, true)) {
-        // Successfully downloaded and read, and it has been written
-        // into its normal place.
-        get_core_api();
-        
-      } else {
-        // Error reading the contents.xml file, or in loading the core
-        // API that it references.
-        nout << "Unable to read contents file " << filename << "\n";
-        
-        // If there's an outstanding contents.xml file on disk, try to
-        // load that one as a fallback.
-        string contents_filename = _root_dir + "/contents.xml";
-        if (read_contents_file(contents_filename, false)) {
-          get_core_api();
-        } else {
-          nout << "Unable to read contents file " << contents_filename << "\n";
-          set_failed();
-        }
-      }
-    }
+    // The contents.xml file that gets things going.
+    downloaded_contents_file(filename);
     break;
     break;
 
 
   case PPDownloadRequest::RT_core_dll:
   case PPDownloadRequest::RT_core_dll:
@@ -1463,9 +1494,8 @@ downloaded_file(PPDownloadRequest *req, const string &filename) {
     break;
     break;
 
 
   case PPDownloadRequest::RT_user:
   case PPDownloadRequest::RT_user:
-    // Normally, RT_user requests won't come here, unless we
-    // short-circuited the browser by "downloading" a file:// url.  In
-    // any case, we'll now open the file and feed it to the user.
+    // Here's the user-requested file.  It needs to be streamed to the
+    // user, so we'll open the file and feed it to the user.
     feed_file(req, filename);
     feed_file(req, filename);
     break;
     break;
 
 
@@ -1487,35 +1517,6 @@ feed_file(PPDownloadRequest *req, const string &filename) {
   _file_datas.push_back(file_data);
   _file_datas.push_back(file_data);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: PPInstance::open_p3d_temp_file
-//       Access: Private
-//  Description: Creates a temporary file into which the p3d file data
-//               is stored before the instance has been created.
-////////////////////////////////////////////////////////////////////
-void PPInstance::
-open_p3d_temp_file() {
-  assert(!_opened_p3d_temp_file);
-  _opened_p3d_temp_file = true;
-  _finished_p3d_temp_file = false;
-  _p3d_temp_file_current_size = 0;
-  _p3d_temp_file_total_size = 0;
-
-  char *name = tempnam(NULL, "p3d_");
-  _p3d_temp_filename = name;
-  free(name);
-
-  _p3d_temp_file.clear();
-  _p3d_temp_file.open(_p3d_temp_filename.c_str(), ios::binary);
-  if (!_p3d_temp_file) {
-    nout << "Unable to open temp file " << _p3d_temp_filename << "\n";
-    set_failed();
-  } else {
-    nout << "Opening " << _p3d_temp_filename
-         << " for storing preliminary p3d data\n";
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PPInstance::send_p3d_temp_file_data
 //     Function: PPInstance::send_p3d_temp_file_data
 //       Access: Private
 //       Access: Private
@@ -1525,10 +1526,10 @@ open_p3d_temp_file() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PPInstance::
 void PPInstance::
 send_p3d_temp_file_data() {
 send_p3d_temp_file_data() {
-  assert(_opened_p3d_temp_file);
+  assert(_p3d_temp_file._opened);
 
 
-  nout << "Sending " << _p3d_temp_file_current_size
-       << " preliminary bytes of " << _p3d_temp_file_total_size
+  nout << "Sending " << _p3d_temp_file._current_size
+       << " preliminary bytes of " << _p3d_temp_file._total_size
        << " total p3d data\n";
        << " total p3d data\n";
         
         
   static const size_t buffer_size = 4096;
   static const size_t buffer_size = 4096;
@@ -1536,14 +1537,14 @@ send_p3d_temp_file_data() {
 
 
   _p3d_temp_file.close();
   _p3d_temp_file.close();
 
 
-  ifstream in(_p3d_temp_filename.c_str(), ios::binary);
+  ifstream in(_p3d_temp_file._filename.c_str(), ios::binary);
   in.read(buffer, buffer_size);
   in.read(buffer, buffer_size);
   size_t total = 0;
   size_t total = 0;
   size_t count = in.gcount();
   size_t count = in.gcount();
   while (count != 0) {
   while (count != 0) {
     P3D_instance_feed_url_stream_ptr(_p3d_inst, _p3d_instance_id,
     P3D_instance_feed_url_stream_ptr(_p3d_inst, _p3d_instance_id,
-                                 P3D_RC_in_progress, 0,
-                                 _p3d_temp_file_total_size, buffer, count);
+                                     P3D_RC_in_progress, 0,
+                                     _p3d_temp_file._total_size, buffer, count);
     total += count;
     total += count;
 
 
     in.read(buffer, buffer_size);
     in.read(buffer, buffer_size);
@@ -1552,16 +1553,14 @@ send_p3d_temp_file_data() {
   nout << "sent " << count << " bytes.\n";
   nout << "sent " << count << " bytes.\n";
 
 
   in.close();
   in.close();
-  _opened_p3d_temp_file = false;
-  unlink(_p3d_temp_filename.c_str());
-  _p3d_temp_filename.clear();
 
 
-  if (_finished_p3d_temp_file) {
+  if (_p3d_temp_file._finished) {
     // If we'd already finished the stream earlier, tell the plugin.
     // If we'd already finished the stream earlier, tell the plugin.
     P3D_instance_feed_url_stream_ptr(_p3d_inst, _p3d_instance_id,
     P3D_instance_feed_url_stream_ptr(_p3d_inst, _p3d_instance_id,
-                                 P3D_RC_done, 0, _p3d_temp_file_total_size,
-                                 NULL, 0);
+                                     P3D_RC_done, 0, _p3d_temp_file._total_size,
+                                     NULL, 0);
   }
   }
+  _p3d_temp_file.cleanup();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1795,7 +1794,7 @@ create_instance() {
 
 
     // If we have already started to receive any instance data, send it
     // If we have already started to receive any instance data, send it
     // to the plugin now.
     // to the plugin now.
-    if (_opened_p3d_temp_file) {
+    if (_p3d_temp_file._opened) {
       send_p3d_temp_file_data();
       send_p3d_temp_file_data();
     }
     }
   }
   }
@@ -2912,3 +2911,130 @@ thread_run() {
   // All done.
   // All done.
   _thread_done = true;
   _thread_done = true;
 }
 }
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PPInstance::StreamTempFile::
+StreamTempFile() {
+  _opened = false;
+  _finished = false;
+  _current_size = 0;
+  _total_size = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PPInstance::StreamTempFile::
+~StreamTempFile() {
+  cleanup();
+}
+    
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::open
+//       Access: Public
+//  Description: Creates the temp file and prepares to write to it.
+//               It is not normally necessary to call this explicitly;
+//               it will be called automatically on the first call to
+//               feed().
+////////////////////////////////////////////////////////////////////
+void PPInstance::StreamTempFile::
+open() {
+  assert(!_opened);
+  _opened = true;
+  _finished = false;
+  _current_size = 0;
+  _total_size = 0;
+
+  char *name = tempnam(NULL, "p3d_");
+  _filename = name;
+  free(name);
+
+  _stream.clear();
+  _stream.open(_filename.c_str(), ios::binary);
+  if (!_stream) {
+    nout << "Unable to open temp file " << _filename << "\n";
+  } else {
+    nout << "Opening " << _filename << "\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::feed
+//       Access: Public
+//  Description: Receives new data from the URL and writes it to the
+//               temp file.  Returns true on success, false on
+//               failure.
+////////////////////////////////////////////////////////////////////
+bool PPInstance::StreamTempFile::
+feed(size_t total_expected_data, const void *this_data,
+     size_t this_data_size) {
+  assert(!_finished);
+  if (!_opened) {
+    open();
+  }
+
+  _stream.write((const char *)this_data, this_data_size);
+  _current_size += this_data_size;
+  _total_size = total_expected_data;
+
+  if (!_stream) {
+    return false;
+  }
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::finish
+//       Access: Public
+//  Description: Marks the end of the data received from the URL.  The
+//               file is closed but not yet deleted; it remains on
+//               disk and may be read at leisure.
+////////////////////////////////////////////////////////////////////
+void PPInstance::StreamTempFile::
+finish() {
+  if (!_finished) {
+    _finished = true;
+    _total_size = _current_size;
+  }
+
+  _stream.close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::close
+//       Access: Public
+//  Description: Closes the stream for more data.  The file is not yet
+//               deleted; it remains on disk and may be read at
+//               leisure.
+////////////////////////////////////////////////////////////////////
+void PPInstance::StreamTempFile::
+close() {
+  _stream.close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::StreamTempFile::cleanup
+//       Access: Public
+//  Description: Closes all open processes and removes the temp file
+//               from disk.
+////////////////////////////////////////////////////////////////////
+void PPInstance::StreamTempFile::
+cleanup() {
+  finish();
+
+  if (!_filename.empty()) {
+    nout << "Deleting " << _filename << "\n";
+    unlink(_filename.c_str());
+    _filename.clear();
+  }
+
+  _opened = false;
+  _finished = false;
+}

+ 26 - 6
direct/src/plugin_npapi/ppInstance.h

@@ -86,6 +86,7 @@ private:
   void open_p3d_temp_file();
   void open_p3d_temp_file();
   void send_p3d_temp_file_data();
   void send_p3d_temp_file_data();
 
 
+  void downloaded_contents_file(const string &filename);
   bool read_contents_file(const string &contents_filename, bool fresh_download);
   bool read_contents_file(const string &contents_filename, bool fresh_download);
   void get_core_api();
   void get_core_api();
   void downloaded_plugin(const string &filename);
   void downloaded_plugin(const string &filename);
@@ -168,15 +169,34 @@ private:
   bool _failed;
   bool _failed;
   bool _started;
   bool _started;
 
 
+  // This class is used to stream data from some URL into a temporary
+  // local file.
+  class StreamTempFile {
+  public:
+    StreamTempFile();
+    ~StreamTempFile();
+    
+    void open();
+    bool feed(size_t total_expected_data, const void *this_data, 
+              size_t this_data_size);
+    void finish();
+    void close();
+    void cleanup();
+
+    bool _opened;
+    bool _finished;
+    size_t _current_size;
+    size_t _total_size;
+    ofstream _stream;
+    string _filename;
+  };
+
   bool _got_instance_url;
   bool _got_instance_url;
   string _instance_url;
   string _instance_url;
-  bool _opened_p3d_temp_file;
-  bool _finished_p3d_temp_file;
-  size_t _p3d_temp_file_current_size;
-  size_t _p3d_temp_file_total_size;
-  ofstream _p3d_temp_file;
-  string _p3d_temp_filename;
   int _p3d_instance_id;
   int _p3d_instance_id;
+  StreamTempFile _p3d_temp_file;
+  StreamTempFile _contents_temp_file;
+  StreamTempFile _core_dll_temp_file;
  
  
   // We need to keep a list of the NPStream objects that the instance
   // We need to keep a list of the NPStream objects that the instance
   // owns, because Safari (at least) won't automatically delete all of
   // owns, because Safari (at least) won't automatically delete all of

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

@@ -17,6 +17,7 @@
 #include "p3d_lock.h"
 #include "p3d_lock.h"
 #include "ppBrowserObject.h"
 #include "ppBrowserObject.h"
 #include "wstring_encode.h"
 #include "wstring_encode.h"
+#include "find_root_dir.h"
 
 
 #ifdef _WIN32
 #ifdef _WIN32
 #include <shlobj.h>
 #include <shlobj.h>