mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
fix safari crash
This commit is contained in:
parent
c8c51528bd
commit
7e565c2a49
@ -73,6 +73,18 @@ get_download_success() const {
|
|||||||
return _status == P3D_RC_done;
|
return _status == P3D_RC_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DDownload::get_download_terminated
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns true if the download has failed because the
|
||||||
|
// instance is about to be shut down, or false if it
|
||||||
|
// hasn't failed, or failed for some other reason.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline bool P3DDownload::
|
||||||
|
get_download_terminated() const {
|
||||||
|
return _status == P3D_RC_shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DDownload::set_download_id
|
// Function: P3DDownload::set_download_id
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -40,6 +40,7 @@ public:
|
|||||||
inline double get_download_progress() const;
|
inline double get_download_progress() const;
|
||||||
inline bool get_download_finished() const;
|
inline bool get_download_finished() const;
|
||||||
inline bool get_download_success() const;
|
inline bool get_download_success() const;
|
||||||
|
inline bool get_download_terminated() const;
|
||||||
inline size_t get_total_data() const;
|
inline size_t get_total_data() const;
|
||||||
|
|
||||||
void cancel();
|
void cancel();
|
||||||
|
@ -712,7 +712,7 @@ got_desc_file(TiXmlDocument *doc, bool freshly_downloaded) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DPackage::clear_install_plans
|
// Function: P3DPackage::clear_install_plans
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description:a Empties _install_plans cleanly.
|
// Description: Empties _install_plans cleanly.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPackage::
|
void P3DPackage::
|
||||||
clear_install_plans() {
|
clear_install_plans() {
|
||||||
@ -883,6 +883,12 @@ follow_install_plans(bool download_finished) {
|
|||||||
plan_failed = true;
|
plan_failed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IT_terminate:
|
||||||
|
// All plans have failed.
|
||||||
|
_install_plans.clear();
|
||||||
|
report_done(false);
|
||||||
|
return;
|
||||||
|
|
||||||
case IT_continue:
|
case IT_continue:
|
||||||
// A callback hook has been attached; we'll come back later.
|
// A callback hook has been attached; we'll come back later.
|
||||||
return;
|
return;
|
||||||
@ -1213,6 +1219,13 @@ download_finished(bool success) {
|
|||||||
close_file();
|
close_file();
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
if (get_download_terminated()) {
|
||||||
|
// Short-circuit the exit.
|
||||||
|
_try_urls.clear();
|
||||||
|
resume_download_finished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Maybe it failed because our contents.xml file is out-of-date.
|
// Maybe it failed because our contents.xml file is out-of-date.
|
||||||
// Go try to freshen it.
|
// Go try to freshen it.
|
||||||
bool is_contents_file = (_dtype == DT_contents_file || _dtype == DT_redownload_contents_file);
|
bool is_contents_file = (_dtype == DT_contents_file || _dtype == DT_redownload_contents_file);
|
||||||
@ -1352,6 +1365,10 @@ do_step(bool download_finished) {
|
|||||||
if (_download->get_download_success()) {
|
if (_download->get_download_success()) {
|
||||||
// The Download object has already validated the hash.
|
// The Download object has already validated the hash.
|
||||||
return IT_step_complete;
|
return IT_step_complete;
|
||||||
|
} else if (_download->get_download_terminated()) {
|
||||||
|
// The download was interrupted because we're shutting down.
|
||||||
|
// Don't try any other plans.
|
||||||
|
return IT_terminate;
|
||||||
} else {
|
} else {
|
||||||
// The Download object has already tried all of the mirrors, and
|
// The Download object has already tried all of the mirrors, and
|
||||||
// they all failed.
|
// they all failed.
|
||||||
|
@ -112,6 +112,7 @@ private:
|
|||||||
IT_step_complete,
|
IT_step_complete,
|
||||||
IT_step_failed,
|
IT_step_failed,
|
||||||
IT_continue,
|
IT_continue,
|
||||||
|
IT_terminate,
|
||||||
};
|
};
|
||||||
|
|
||||||
class InstallStep {
|
class InstallStep {
|
||||||
|
@ -831,6 +831,12 @@ typedef enum {
|
|||||||
There may or may not be data associated with this error as well.
|
There may or may not be data associated with this error as well.
|
||||||
However, no more data will be delivered after this call. */
|
However, no more data will be delivered after this call. */
|
||||||
P3D_RC_http_error,
|
P3D_RC_http_error,
|
||||||
|
|
||||||
|
/* The download was interrupted because we're about to shut down the
|
||||||
|
instance. The instance should not attempt to restart a new
|
||||||
|
download in response to this. */
|
||||||
|
P3D_RC_shutdown
|
||||||
|
|
||||||
} P3D_result_code;
|
} P3D_result_code;
|
||||||
|
|
||||||
/* This function is used by the host to handle a get_url request,
|
/* This function is used by the host to handle a get_url request,
|
||||||
|
@ -84,6 +84,8 @@ PPInstance::
|
|||||||
_p3d_inst = NULL;
|
_p3d_inst = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(_streams.empty());
|
||||||
|
|
||||||
if (_script_object != NULL) {
|
if (_script_object != NULL) {
|
||||||
browser->releaseobject(_script_object);
|
browser->releaseobject(_script_object);
|
||||||
}
|
}
|
||||||
@ -187,6 +189,8 @@ set_window(NPWindow *window) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
NPError PPInstance::
|
NPError PPInstance::
|
||||||
new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
|
new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
|
||||||
|
assert(find(_streams.begin(), _streams.end(), stream) == _streams.end());
|
||||||
|
|
||||||
if (stream->notifyData == NULL) {
|
if (stream->notifyData == NULL) {
|
||||||
// This is an unsolicited stream. Assume the first unsolicited
|
// This is an unsolicited stream. Assume the first unsolicited
|
||||||
// stream we receive is the instance data; any other unsolicited
|
// stream we receive is the instance data; any other unsolicited
|
||||||
@ -198,6 +202,7 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
|
|||||||
stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_instance_data);
|
stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_instance_data);
|
||||||
|
|
||||||
*stype = NP_NORMAL;
|
*stype = NP_NORMAL;
|
||||||
|
_streams.push_back(stream);
|
||||||
return NPERR_NO_ERROR;
|
return NPERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,18 +216,21 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
|
|||||||
// This is the initial contents.xml file. We'll just download
|
// This is the initial contents.xml file. We'll just download
|
||||||
// this directly 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;
|
*stype = NP_ASFILEONLY;
|
||||||
|
_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
|
// This is the core API DLL (or dylib or whatever). We want to
|
||||||
// download this to file for convenience.
|
// download this to file for convenience.
|
||||||
*stype = NP_ASFILEONLY;
|
*stype = NP_ASFILEONLY;
|
||||||
|
_streams.push_back(stream);
|
||||||
return NPERR_NO_ERROR;
|
return NPERR_NO_ERROR;
|
||||||
|
|
||||||
case PPDownloadRequest::RT_user:
|
case PPDownloadRequest::RT_user:
|
||||||
// This is a request from the plugin. We'll receive this as a
|
// This is a request from the plugin. We'll receive this as a
|
||||||
// stream.
|
// stream.
|
||||||
*stype = NP_NORMAL;
|
*stype = NP_NORMAL;
|
||||||
|
_streams.push_back(stream);
|
||||||
return NPERR_NO_ERROR;
|
return NPERR_NO_ERROR;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -233,6 +241,29 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
|
|||||||
return NPERR_GENERIC_ERROR;
|
return NPERR_GENERIC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPInstance::stop_outstanding_streams
|
||||||
|
// Access: Public
|
||||||
|
// Description: Stops any download streams that are currently active
|
||||||
|
// on the instance. It is necessary to call this
|
||||||
|
// explicitly before destroying the instance, at least
|
||||||
|
// for Safari.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPInstance::
|
||||||
|
stop_outstanding_streams() {
|
||||||
|
Streams::iterator si;
|
||||||
|
Streams streams;
|
||||||
|
streams.swap(_streams);
|
||||||
|
for (si = streams.begin(); si != streams.end(); ++si) {
|
||||||
|
NPStream *stream = (*si);
|
||||||
|
nout << "Stopping stream " << stream->url << "\n";
|
||||||
|
browser->destroystream(_npp_instance, stream, NPRES_USER_BREAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_streams.empty());
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPInstance::write_ready
|
// Function: PPInstance::write_ready
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -310,6 +341,13 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
NPError PPInstance::
|
NPError PPInstance::
|
||||||
destroy_stream(NPStream *stream, NPReason reason) {
|
destroy_stream(NPStream *stream, NPReason reason) {
|
||||||
|
Streams::iterator si = find(_streams.begin(), _streams.end(), stream);
|
||||||
|
if (si == _streams.end()) {
|
||||||
|
nout << "Got destroy_stream for unknown stream\n";
|
||||||
|
} else {
|
||||||
|
_streams.erase(si);
|
||||||
|
}
|
||||||
|
|
||||||
if (stream->notifyData == NULL) {
|
if (stream->notifyData == NULL) {
|
||||||
nout << "Unexpected destroy_stream on " << stream->url << "\n";
|
nout << "Unexpected destroy_stream on " << stream->url << "\n";
|
||||||
return NPERR_NO_ERROR;
|
return NPERR_NO_ERROR;
|
||||||
@ -321,7 +359,11 @@ destroy_stream(NPStream *stream, NPReason reason) {
|
|||||||
{
|
{
|
||||||
P3D_result_code result_code = P3D_RC_done;
|
P3D_result_code result_code = P3D_RC_done;
|
||||||
if (reason != NPRES_DONE) {
|
if (reason != NPRES_DONE) {
|
||||||
result_code = P3D_RC_generic_error;
|
if (reason == NPRES_USER_BREAK) {
|
||||||
|
result_code = P3D_RC_shutdown;
|
||||||
|
} else {
|
||||||
|
result_code = P3D_RC_generic_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(!req->_notified_done);
|
assert(!req->_notified_done);
|
||||||
P3D_instance_feed_url_stream(_p3d_inst, req->_user_id,
|
P3D_instance_feed_url_stream(_p3d_inst, req->_user_id,
|
||||||
@ -330,6 +372,12 @@ destroy_stream(NPStream *stream, NPReason reason) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
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.
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
nout << "Unexpected destroy_stream on " << stream->url << "\n";
|
nout << "Unexpected destroy_stream on " << stream->url << "\n";
|
||||||
break;
|
break;
|
||||||
@ -372,13 +420,17 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
|
|||||||
if (reason != NPRES_DONE) {
|
if (reason != NPRES_DONE) {
|
||||||
nout << "Failure downloading " << url << "\n";
|
nout << "Failure downloading " << url << "\n";
|
||||||
|
|
||||||
// Couldn't download a fresh contents.xml for some reason. If
|
if (reason == NPRES_USER_BREAK) {
|
||||||
// there's an outstanding contents.xml file on disk, try to load
|
nout << "Failure due to user break\n";
|
||||||
// that one as a fallback.
|
} else {
|
||||||
string contents_filename = _root_dir + "/contents.xml";
|
// Couldn't download a fresh contents.xml for some reason. If
|
||||||
if (!read_contents_file(contents_filename)) {
|
// there's an outstanding contents.xml file on disk, try to
|
||||||
nout << "Unable to read contents file " << contents_filename << "\n";
|
// load that one as a fallback.
|
||||||
// TODO: fail
|
string contents_filename = _root_dir + "/contents.xml";
|
||||||
|
if (!read_contents_file(contents_filename)) {
|
||||||
|
nout << "Unable to read contents file " << contents_filename << "\n";
|
||||||
|
// TODO: fail
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -386,13 +438,18 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
|
|||||||
case PPDownloadRequest::RT_core_dll:
|
case PPDownloadRequest::RT_core_dll:
|
||||||
if (reason != NPRES_DONE) {
|
if (reason != NPRES_DONE) {
|
||||||
nout << "Failure downloading " << url << "\n";
|
nout << "Failure downloading " << url << "\n";
|
||||||
// Couldn't download from this mirror. Try the next one.
|
|
||||||
if (!_core_urls.empty()) {
|
|
||||||
string url = _core_urls.back();
|
|
||||||
_core_urls.pop_back();
|
|
||||||
|
|
||||||
PPDownloadRequest *req2 = new PPDownloadRequest(PPDownloadRequest::RT_core_dll);
|
if (reason == NPRES_USER_BREAK) {
|
||||||
start_download(url, req2);
|
nout << "Failure due to user break\n";
|
||||||
|
} else {
|
||||||
|
// Couldn't download from this mirror. Try the next one.
|
||||||
|
if (!_core_urls.empty()) {
|
||||||
|
string url = _core_urls.back();
|
||||||
|
_core_urls.pop_back();
|
||||||
|
|
||||||
|
PPDownloadRequest *req2 = new PPDownloadRequest(PPDownloadRequest::RT_core_dll);
|
||||||
|
start_download(url, req2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -46,6 +46,7 @@ public:
|
|||||||
void set_window(NPWindow *window);
|
void set_window(NPWindow *window);
|
||||||
NPError new_stream(NPMIMEType type, NPStream *stream,
|
NPError new_stream(NPMIMEType type, NPStream *stream,
|
||||||
bool seekable, uint16 *stype);
|
bool seekable, uint16 *stype);
|
||||||
|
void stop_outstanding_streams();
|
||||||
|
|
||||||
int32 write_ready(NPStream *stream);
|
int32 write_ready(NPStream *stream);
|
||||||
int write_stream(NPStream *stream, int offset, int len, void *buffer);
|
int write_stream(NPStream *stream, int offset, int len, void *buffer);
|
||||||
@ -117,6 +118,12 @@ private:
|
|||||||
bool _got_instance_url;
|
bool _got_instance_url;
|
||||||
string _instance_url;
|
string _instance_url;
|
||||||
|
|
||||||
|
// We need to keep a list of the NPStream objects that the instance
|
||||||
|
// owns, because Safari (at least) won't automatically delete all of
|
||||||
|
// the outstanding streams when the instance is destroyed.
|
||||||
|
typedef vector<NPStream *> Streams;
|
||||||
|
Streams _streams;
|
||||||
|
|
||||||
// This class is used for feeding local files (accessed via a
|
// This class is used for feeding local files (accessed via a
|
||||||
// "file://" url) into the core API.
|
// "file://" url) into the core API.
|
||||||
class StreamingFileData {
|
class StreamingFileData {
|
||||||
|
@ -243,11 +243,12 @@ NP_Shutdown(void) {
|
|||||||
NPError
|
NPError
|
||||||
NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
|
NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
|
||||||
int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
|
int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
|
||||||
nout << "new instance\n";
|
nout << "new instance " << instance << "\n";
|
||||||
|
|
||||||
PPInstance *inst = new PPInstance(pluginType, instance, mode,
|
PPInstance *inst = new PPInstance(pluginType, instance, mode,
|
||||||
argc, argn, argv, saved);
|
argc, argn, argv, saved);
|
||||||
instance->pdata = inst;
|
instance->pdata = inst;
|
||||||
|
nout << "new instance->pdata = " << inst << "\n";
|
||||||
|
|
||||||
// To experiment with a "windowless" plugin, which really means we
|
// To experiment with a "windowless" plugin, which really means we
|
||||||
// create our own window without an intervening window, try this.
|
// create our own window without an intervening window, try this.
|
||||||
@ -267,10 +268,15 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
NPError
|
NPError
|
||||||
NPP_Destroy(NPP instance, NPSavedData **save) {
|
NPP_Destroy(NPP instance, NPSavedData **save) {
|
||||||
nout << "destroy instance " << instance << "\n";
|
nout << "destroy instance " << instance << ", "
|
||||||
|
<< (PPInstance *)instance->pdata << "\n";
|
||||||
nout << "save = " << (void *)save << "\n";
|
nout << "save = " << (void *)save << "\n";
|
||||||
// (*save) = NULL;
|
// (*save) = NULL;
|
||||||
delete (PPInstance *)(instance->pdata);
|
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||||
|
assert(inst != NULL);
|
||||||
|
inst->stop_outstanding_streams();
|
||||||
|
|
||||||
|
delete inst;
|
||||||
instance->pdata = NULL;
|
instance->pdata = NULL;
|
||||||
|
|
||||||
return NPERR_NO_ERROR;
|
return NPERR_NO_ERROR;
|
||||||
@ -330,7 +336,8 @@ NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
|
|||||||
<< ", " << stream->end
|
<< ", " << stream->end
|
||||||
<< ", notifyData = " << stream->notifyData
|
<< ", notifyData = " << stream->notifyData
|
||||||
<< ", reason = " << reason
|
<< ", reason = " << reason
|
||||||
<< "\n";
|
<< ", for " << instance
|
||||||
|
<< ", " << (PPInstance *)(instance->pdata) << "\n";
|
||||||
|
|
||||||
PPInstance::generic_browser_call();
|
PPInstance::generic_browser_call();
|
||||||
PPInstance *inst = (PPInstance *)(instance->pdata);
|
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||||
@ -346,6 +353,7 @@ NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int32
|
int32
|
||||||
NPP_WriteReady(NPP instance, NPStream *stream) {
|
NPP_WriteReady(NPP instance, NPStream *stream) {
|
||||||
|
// nout << "WriteReady " << stream->url << " for " << instance << ", " << (PPInstance *)(instance->pdata) << "\n";
|
||||||
PPInstance::generic_browser_call();
|
PPInstance::generic_browser_call();
|
||||||
PPInstance *inst = (PPInstance *)(instance->pdata);
|
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||||
assert(inst != NULL);
|
assert(inst != NULL);
|
||||||
@ -362,7 +370,7 @@ NPP_WriteReady(NPP instance, NPStream *stream) {
|
|||||||
int32
|
int32
|
||||||
NPP_Write(NPP instance, NPStream *stream, int32 offset,
|
NPP_Write(NPP instance, NPStream *stream, int32 offset,
|
||||||
int32 len, void *buffer) {
|
int32 len, void *buffer) {
|
||||||
// nout << "Write " << stream->url << ", " << len << "\n";
|
// nout << "Write " << stream->url << ", " << len << " for " << instance << ", " << (PPInstance *)(instance->pdata) << "\n";
|
||||||
PPInstance::generic_browser_call();
|
PPInstance::generic_browser_call();
|
||||||
PPInstance *inst = (PPInstance *)(instance->pdata);
|
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||||
assert(inst != NULL);
|
assert(inst != NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user