fix some startup issues
This commit is contained in:
parent
c9f091d1e6
commit
795c8c0fc5
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue