fix some startup issues

This commit is contained in:
David Rose 2009-07-08 18:14:25 +00:00
parent c9f091d1e6
commit 795c8c0fc5
3 changed files with 182 additions and 45 deletions

View File

@ -52,14 +52,6 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
_started_instance_data = false;
_got_instance_data = false;
_got_window = false;
if (!is_plugin_loaded()) {
// Go download the contents file, so we can download the core DLL.
string url = P3D_PLUGIN_DOWNLOAD;
url += "contents.xml";
PPDownloadRequest *req = new PPDownloadRequest(PPDownloadRequest::RT_contents_file);
browser->geturlnotify(_npp_instance, url.c_str(), NULL, req);
}
}
////////////////////////////////////////////////////////////////////
@ -99,6 +91,27 @@ PPInstance::
_tokens.clear();
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::begin
// Access: Public
// Description: Begins the initial download of the core API. This
// should be called after constructing the PPInstance.
// It is a separate method than the constructor, because
// it initiates some callbacks that might rely on the
// object having been fully constructed and its pointer
// stored.
////////////////////////////////////////////////////////////////////
void PPInstance::
begin() {
if (!is_plugin_loaded()) {
// Go download the contents file, so we can download the core DLL.
string url = P3D_PLUGIN_DOWNLOAD;
url += "contents.xml";
PPDownloadRequest *req = new PPDownloadRequest(PPDownloadRequest::RT_contents_file);
start_download(url, req);
}
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::set_window
// Access: Public
@ -172,7 +185,7 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
switch (req->_rtype) {
case PPDownloadRequest::RT_contents_file:
// This is the initial contents.xml file. We'll just download
// this directoy to a file, since it is small and this is easy.
// this directly to a file, since it is small and this is easy.
*stype = NP_ASFILEONLY;
return NPERR_NO_ERROR;
@ -290,6 +303,13 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
req->_notified_done = true;
}
break;
case PPDownloadRequest::RT_contents_file:
if (reason != NPRES_DONE) {
logfile << "Failure downloading " << url << "\n";
// TODO: fail
}
break;
default:
break;
@ -345,34 +365,7 @@ stream_as_file(NPStream *stream, const char *fname) {
#endif // __APPLE__
PPDownloadRequest *req = (PPDownloadRequest *)(stream->notifyData);
switch (req->_rtype) {
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)) {
logfile << "Unable to read contents file\n";
// TODO: fail
}
break;
case PPDownloadRequest::RT_core_dll:
// This is the core API DLL (or dylib or whatever). Now that
// we've downloaded it, we can load it.
downloaded_plugin(filename);
break;
case PPDownloadRequest::RT_instance_data:
// This is the instance data, e.g. the p3d filename. Now we can
// launch the instance.
_got_instance_data = true;
_p3d_filename = filename;
create_instance();
break;
default:
// Don't know what this is.
logfile << "Unexpected stream_as_file, type " << (int)req->_rtype << "\n";
}
downloaded_file(req, filename);
}
////////////////////////////////////////////////////////////////////
@ -402,8 +395,7 @@ handle_request(P3D_request *request) {
PPDownloadRequest *req =
new PPDownloadRequest(PPDownloadRequest::RT_user,
request->_request._get_url._unique_id);
browser->geturlnotify(_npp_instance, request->_request._get_url._url,
NULL, req);
start_download(request->_request._get_url._url, req);
}
break;
@ -486,7 +478,7 @@ get_panda_script_object() {
////////////////////////////////////////////////////////////////////
// Function: PPInstance::p3dobj_to_variant
// Access: Private
// Access: Public
// Description: Converts the indicated P3D_object to the equivalent
// NPVariant, and stores it in result.
////////////////////////////////////////////////////////////////////
@ -533,7 +525,7 @@ p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
////////////////////////////////////////////////////////////////////
// Function: PPInstance::variant_to_p3dobj
// Access: Private
// Access: Public
// Description: Converts the indicated NPVariant to the equivalent
// P3D_object, and returns it (newly-allocated). The
// caller is responsible for freeing the returned object
@ -562,6 +554,23 @@ variant_to_p3dobj(const NPVariant *variant) {
return P3D_new_none_object();
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::start_download
// Access: Private
// Description: Initiates a download request.
////////////////////////////////////////////////////////////////////
void PPInstance::
start_download(const string &url, PPDownloadRequest *req) {
if (url.substr(0, 7) == "file://") {
// If we're "downloading" a file URL, just go read the file directly.
downloaded_file(req, get_filename_from_url(url));
delete req;
} else {
// Otherwise, ask the browser to download it.
browser->geturlnotify(_npp_instance, url.c_str(), NULL, req);
}
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::read_contents_file
// Access: Private
@ -591,6 +600,122 @@ read_contents_file(const string &filename) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::get_filename_from_url
// Access: Private, Static
// Description: Returns the actual filename referenced by a file://
// url.
////////////////////////////////////////////////////////////////////
string PPInstance::
get_filename_from_url(const string &url) {
string filename = url.substr(7);
#ifdef _WIN32
// On Windows, we have to munge the filename specially, because it's
// been URL-munged. It might begin with a leading slash as well as
// a drive letter. Clean up that nonsense.
if (filename.length() >= 3 &&
(filename[0] == '/' || filename[0] == '\\') &&
isalpha(filename[1]) && filename[2] == ':') {
filename = filename.substr(1);
}
#endif // _WIN32
return filename;
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::downloaded_file
// Access: Private
// Description: Called to receive the fully-downloaded contents of a
// URL.
////////////////////////////////////////////////////////////////////
void PPInstance::
downloaded_file(PPDownloadRequest *req, const string &filename) {
switch (req->_rtype) {
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)) {
logfile << "Unable to read contents file\n";
// TODO: fail
}
break;
case PPDownloadRequest::RT_core_dll:
// This is the core API DLL (or dylib or whatever). Now that
// we've downloaded it, we can load it.
downloaded_plugin(filename);
break;
case PPDownloadRequest::RT_instance_data:
// This is the instance data, e.g. the p3d filename. Now we can
// launch the instance.
_got_instance_data = true;
_p3d_filename = filename;
create_instance();
break;
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.
feed_file(req, filename);
break;
default:
// Don't know what this is.
logfile << "Unexpected downloaded file, type " << (int)req->_rtype << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::feed_file
// Access: Private
// Description: Opens the named file (extracted from a file:// URL)
// and feeds its contents to the plugin.
////////////////////////////////////////////////////////////////////
void PPInstance::
feed_file(PPDownloadRequest *req, const string &filename) {
ifstream file(filename.c_str(), ios::in | ios::binary);
// First, seek to the end to get the file size.
file.seekg(0, ios::end);
size_t file_size = file.tellg();
// Then return to the beginning to read the data.
file.seekg(0, ios::beg);
static const size_t buffer_size = 4096;
char buffer[buffer_size];
file.read(buffer, buffer_size);
size_t count = file.gcount();
size_t total_count = 0;
while (count != 0) {
bool download_ok = P3D_instance_feed_url_stream
(_p3d_inst, req->_user_id, P3D_RC_in_progress,
0, file_size, (const unsigned char *)buffer, count);
if (!download_ok) {
// Never mind.
return;
}
file.read(buffer, buffer_size);
count = file.gcount();
total_count += count;
}
P3D_result_code result = P3D_RC_done;
if (file.fail() && !file.eof()) {
// Got an error while reading.
result = P3D_RC_generic_error;
}
P3D_instance_feed_url_stream
(_p3d_inst, req->_user_id, result, 0, total_count, NULL, 0);
}
////////////////////////////////////////////////////////////////////
// Function: PPInstance::get_core_api
// Access: Private
@ -614,7 +739,7 @@ get_core_api(TiXmlElement *xpackage) {
url += _core_api_dll.get_filename();
PPDownloadRequest *req = new PPDownloadRequest(PPDownloadRequest::RT_core_dll);
browser->geturlnotify(_npp_instance, url.c_str(), NULL, req);
start_download(url, req);
}
}

View File

@ -22,6 +22,7 @@
#include <vector>
class PPPandaObject;
class PPDownloadRequest;
////////////////////////////////////////////////////////////////////
// Class : PPInstance
@ -36,6 +37,8 @@ public:
int16 argc, char *argn[], char *argv[], NPSavedData *saved);
~PPInstance();
void begin();
inline NPP get_npp_instance() const;
inline const NPWindow *get_window() const;
@ -56,6 +59,11 @@ public:
P3D_object *variant_to_p3dobj(const NPVariant *variant);
private:
void start_download(const string &url, PPDownloadRequest *req);
void downloaded_file(PPDownloadRequest *req, const string &filename);
static string get_filename_from_url(const string &url);
void feed_file(PPDownloadRequest *req, const string &filename);
bool read_contents_file(const string &filename);
void get_core_api(TiXmlElement *xpackage);
void downloaded_plugin(const string &filename);

View File

@ -201,8 +201,9 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
logfile << "new instance\n" << flush;
instance->pdata = new PPInstance(pluginType, instance, mode,
argc, argn, argv, saved);
PPInstance *inst = new PPInstance(pluginType, instance, mode,
argc, argn, argv, saved);
instance->pdata = inst;
// To experiment with a "windowless" plugin, which really means we
// create our own window without an intervening window, try this.
@ -210,6 +211,10 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
// surely it can be solved.
// browser->setvalue(instance, NPPVpluginWindowBool, (void *)false);
// Now that we have stored the pointer, we can call begin(), which
// starts to initiate downloads.
inst->begin();
return NPERR_NO_ERROR;
}
@ -331,7 +336,6 @@ NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) {
<< ", " << stream->end
<< ", notifyData = " << stream->notifyData
<< "\n" << flush;
logfile << "filename: " << fname << "\n" << flush;
PPInstance *inst = (PPInstance *)(instance->pdata);
assert(inst != NULL);