mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-22 17:06:36 -06:00
Bug 798702 - Crash in gnc_plugin_page_focus_idle_destroy() closing...
a report before it completes. The problem was that the progress bar runs the event loop and lets tab get destroyed while the stream handler is running, taking the page and html objects along with it. Then the stream handler returns and the callers try to use the freed page and html objects. Crash. To avoid this take out weak pointers on the page and html and only use the page and html if the respective finalize functions haven't NULLed the weak pointer.
This commit is contained in:
parent
1085d8920b
commit
edf5a8783d
@ -350,6 +350,7 @@ gnc_plugin_page_report_load_uri (GncPluginPage *page)
|
|||||||
{
|
{
|
||||||
GncPluginPageReport *report;
|
GncPluginPageReport *report;
|
||||||
GncPluginPageReportPrivate *priv;
|
GncPluginPageReportPrivate *priv;
|
||||||
|
GncPluginPage *weak_page = page;
|
||||||
URLType type;
|
URLType type;
|
||||||
char * id_name;
|
char * id_name;
|
||||||
char * child_name;
|
char * child_name;
|
||||||
@ -373,6 +374,7 @@ gnc_plugin_page_report_load_uri (GncPluginPage *page)
|
|||||||
g_free(id_name);
|
g_free(id_name);
|
||||||
g_free(child_name);
|
g_free(child_name);
|
||||||
|
|
||||||
|
g_object_add_weak_pointer(G_OBJECT(page), (gpointer*)(&weak_page));
|
||||||
gtk_widget_show_all( GTK_WIDGET(priv->container) );
|
gtk_widget_show_all( GTK_WIDGET(priv->container) );
|
||||||
|
|
||||||
priv->loaded = TRUE;
|
priv->loaded = TRUE;
|
||||||
@ -386,7 +388,11 @@ gnc_plugin_page_report_load_uri (GncPluginPage *page)
|
|||||||
gnc_html_show_url(priv->html, type, url_location, url_label, 0);
|
gnc_html_show_url(priv->html, type, url_location, url_label, 0);
|
||||||
g_free(url_location);
|
g_free(url_location);
|
||||||
|
|
||||||
|
if (weak_page)
|
||||||
|
{
|
||||||
gnc_plugin_page_report_set_progressbar( page, FALSE );
|
gnc_plugin_page_report_set_progressbar( page, FALSE );
|
||||||
|
g_object_remove_weak_pointer(G_OBJECT(page), (gpointer*)(&weak_page));
|
||||||
|
}
|
||||||
|
|
||||||
// this resets the window for the progressbar to NULL
|
// this resets the window for the progressbar to NULL
|
||||||
gnc_window_set_progressbar_window( NULL );
|
gnc_window_set_progressbar_window( NULL );
|
||||||
|
@ -465,7 +465,7 @@ handle_embedded_object( GncHtmlWebkit* self, gchar* html_str )
|
|||||||
* widget.
|
* widget.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
load_to_stream( GncHtmlWebkit* self, URLType type,
|
load_to_stream( GncHtmlWebkit* self, URLType type,
|
||||||
const gchar* location, const gchar* label )
|
const gchar* location, const gchar* label )
|
||||||
{
|
{
|
||||||
@ -485,30 +485,45 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
|
stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
|
||||||
if ( stream_handler )
|
if ( stream_handler )
|
||||||
{
|
{
|
||||||
gboolean ok = stream_handler( location, &fdata, &fdata_len );
|
GncHtml *weak_html = GNC_HTML(self);
|
||||||
|
gboolean ok;
|
||||||
|
|
||||||
if ( ok )
|
g_object_add_weak_pointer(G_OBJECT(self), (gpointer *)(&weak_html));
|
||||||
{
|
|
||||||
fdata = fdata ? fdata : g_strdup( "" );
|
|
||||||
|
|
||||||
// Until webkitgtk supports download requests, look for "<object classid="
|
ok = stream_handler(location, &fdata, &fdata_len);
|
||||||
// indicating the beginning of an embedded graph. If found, handle it
|
|
||||||
if ( g_strstr_len( fdata, -1, "<object classid=" ) != NULL )
|
if (!weak_html) // will be NULL if self has been destroyed
|
||||||
{
|
{
|
||||||
gchar* new_fdata;
|
g_free (fdata);
|
||||||
new_fdata = handle_embedded_object( self, fdata );
|
return FALSE;
|
||||||
g_free( fdata );
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_object_remove_weak_pointer(G_OBJECT(self),
|
||||||
|
(gpointer*)(&weak_html));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
fdata = fdata ? fdata : g_strdup("");
|
||||||
|
|
||||||
|
// Until webkitgtk supports download requests, look for "<object
|
||||||
|
// classid=" indicating the beginning of an embedded graph. If
|
||||||
|
// found, handle it
|
||||||
|
if (g_strstr_len(fdata, -1, "<object classid=") != NULL) {
|
||||||
|
gchar *new_fdata;
|
||||||
|
new_fdata = handle_embedded_object(self, fdata);
|
||||||
|
g_free(fdata);
|
||||||
fdata = new_fdata;
|
fdata = new_fdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save a copy for export purposes
|
// Save a copy for export purposes
|
||||||
if ( priv->html_string != NULL )
|
if (priv->html_string != NULL) {
|
||||||
{
|
g_free(priv->html_string);
|
||||||
g_free( priv->html_string );
|
|
||||||
}
|
}
|
||||||
priv->html_string = g_strdup( fdata );
|
priv->html_string = g_strdup(fdata);
|
||||||
impl_webkit_show_data( GNC_HTML(self), fdata, strlen(fdata) );
|
impl_webkit_show_data(GNC_HTML(self), fdata, strlen(fdata));
|
||||||
// webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
|
// webkit_web_view_load_html_string( priv->web_view,
|
||||||
|
// fdata, BASE_URI_NAME );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -529,7 +544,7 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
/* No action required: Webkit jumps to the anchor on its own. */
|
/* No action required: Webkit jumps to the anchor on its own. */
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,6 +593,7 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
|
|
||||||
}
|
}
|
||||||
while ( FALSE );
|
while ( FALSE );
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -831,6 +847,7 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
GncHTMLUrlCB url_handler;
|
GncHTMLUrlCB url_handler;
|
||||||
gboolean new_window;
|
gboolean new_window;
|
||||||
GncHtmlWebkitPrivate* priv;
|
GncHtmlWebkitPrivate* priv;
|
||||||
|
gboolean stream_loaded = FALSE;
|
||||||
|
|
||||||
g_return_if_fail( self != NULL );
|
g_return_if_fail( self != NULL );
|
||||||
g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
|
g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
|
||||||
@ -921,10 +938,11 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
DEBUG( "resetting base location to %s",
|
DEBUG( "resetting base location to %s",
|
||||||
priv->base.base_location ? priv->base.base_location : "(null)" );
|
priv->base.base_location ? priv->base.base_location : "(null)" );
|
||||||
|
|
||||||
load_to_stream( GNC_HTML_WEBKIT(self), result.url_type,
|
stream_loaded = load_to_stream( GNC_HTML_WEBKIT(self),
|
||||||
|
result.url_type,
|
||||||
new_location, new_label );
|
new_location, new_label );
|
||||||
|
|
||||||
if ( priv->base.load_cb != NULL )
|
if ( stream_loaded && priv->base.load_cb != NULL )
|
||||||
{
|
{
|
||||||
priv->base.load_cb( GNC_HTML(self), result.url_type,
|
priv->base.load_cb( GNC_HTML(self), result.url_type,
|
||||||
new_location, new_label, priv->base.load_cb_data );
|
new_location, new_label, priv->base.load_cb_data );
|
||||||
@ -987,7 +1005,8 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
/* FIXME : handle new_window = 1 */
|
/* FIXME : handle new_window = 1 */
|
||||||
gnc_html_history_append( priv->base.history,
|
gnc_html_history_append( priv->base.history,
|
||||||
gnc_html_history_node_new( type, location, label ) );
|
gnc_html_history_node_new( type, location, label ) );
|
||||||
load_to_stream( GNC_HTML_WEBKIT(self), type, location, label );
|
stream_loaded = load_to_stream( GNC_HTML_WEBKIT(self), type,
|
||||||
|
location, label );
|
||||||
|
|
||||||
}
|
}
|
||||||
while ( FALSE );
|
while ( FALSE );
|
||||||
@ -998,7 +1017,7 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
PERR( "URLType %s not supported.", type );
|
PERR( "URLType %s not supported.", type );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( priv->base.load_cb != NULL )
|
if ( stream_loaded && priv->base.load_cb != NULL )
|
||||||
{
|
{
|
||||||
(priv->base.load_cb)( GNC_HTML(self), type, location, label, priv->base.load_cb_data );
|
(priv->base.load_cb)( GNC_HTML(self), type, location, label, priv->base.load_cb_data );
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,7 @@ handle_embedded_object( GncHtmlWebkit* self, gchar* html_str )
|
|||||||
* widget.
|
* widget.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
load_to_stream( GncHtmlWebkit* self, URLType type,
|
load_to_stream( GncHtmlWebkit* self, URLType type,
|
||||||
const gchar* location, const gchar* label )
|
const gchar* location, const gchar* label )
|
||||||
{
|
{
|
||||||
@ -477,7 +477,7 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
DEBUG( "type %s, location %s, label %s", type ? type : "(null)",
|
DEBUG( "type %s, location %s, label %s", type ? type : "(null)",
|
||||||
location ? location : "(null)", label ? label : "(null)");
|
location ? location : "(null)", label ? label : "(null)");
|
||||||
|
|
||||||
g_return_if_fail( self != NULL );
|
g_return_val_if_fail( self != NULL, FALSE );
|
||||||
|
|
||||||
if ( gnc_html_stream_handlers != NULL )
|
if ( gnc_html_stream_handlers != NULL )
|
||||||
{
|
{
|
||||||
@ -486,7 +486,23 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
|
stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
|
||||||
if ( stream_handler )
|
if ( stream_handler )
|
||||||
{
|
{
|
||||||
gboolean ok = stream_handler( location, &fdata, &fdata_len );
|
GncHtml *weak_html = GNC_HTML(self);
|
||||||
|
gboolean ok;
|
||||||
|
|
||||||
|
g_object_add_weak_pointer(G_OBJECT(self),
|
||||||
|
(gpointer*)(&weak_html));
|
||||||
|
ok = stream_handler( location, &fdata, &fdata_len );
|
||||||
|
|
||||||
|
if (!weak_html) // will be NULL if self has been destroyed
|
||||||
|
{
|
||||||
|
g_free (fdata);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_object_remove_weak_pointer(G_OBJECT(self),
|
||||||
|
(gpointer*)(&weak_html));
|
||||||
|
}
|
||||||
|
|
||||||
if ( ok )
|
if ( ok )
|
||||||
{
|
{
|
||||||
@ -533,7 +549,7 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
}
|
}
|
||||||
/* No action required: Webkit jumps to the anchor on its own. */
|
/* No action required: Webkit jumps to the anchor on its own. */
|
||||||
}
|
}
|
||||||
return;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,7 +596,9 @@ load_to_stream( GncHtmlWebkit* self, URLType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ( FALSE );
|
while ( FALSE );
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
perform_navigation_policy (WebKitWebView *web_view,
|
perform_navigation_policy (WebKitWebView *web_view,
|
||||||
WebKitNavigationPolicyDecision *decision,
|
WebKitNavigationPolicyDecision *decision,
|
||||||
@ -782,6 +800,7 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
GncHTMLUrlCB url_handler;
|
GncHTMLUrlCB url_handler;
|
||||||
gboolean new_window;
|
gboolean new_window;
|
||||||
GncHtmlWebkitPrivate* priv;
|
GncHtmlWebkitPrivate* priv;
|
||||||
|
gboolean stream_loaded = FALSE;
|
||||||
|
|
||||||
g_return_if_fail( self != NULL );
|
g_return_if_fail( self != NULL );
|
||||||
g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
|
g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
|
||||||
@ -872,10 +891,11 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
DEBUG( "resetting base location to %s",
|
DEBUG( "resetting base location to %s",
|
||||||
priv->base.base_location ? priv->base.base_location : "(null)" );
|
priv->base.base_location ? priv->base.base_location : "(null)" );
|
||||||
|
|
||||||
load_to_stream( GNC_HTML_WEBKIT(self), result.url_type,
|
stream_loaded = load_to_stream( GNC_HTML_WEBKIT(self),
|
||||||
|
result.url_type,
|
||||||
new_location, new_label );
|
new_location, new_label );
|
||||||
|
|
||||||
if ( priv->base.load_cb != NULL )
|
if ( stream_loaded && priv->base.load_cb != NULL )
|
||||||
{
|
{
|
||||||
priv->base.load_cb( GNC_HTML(self), result.url_type,
|
priv->base.load_cb( GNC_HTML(self), result.url_type,
|
||||||
new_location, new_label, priv->base.load_cb_data );
|
new_location, new_label, priv->base.load_cb_data );
|
||||||
@ -938,7 +958,8 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
/* FIXME : handle new_window = 1 */
|
/* FIXME : handle new_window = 1 */
|
||||||
gnc_html_history_append( priv->base.history,
|
gnc_html_history_append( priv->base.history,
|
||||||
gnc_html_history_node_new( type, location, label ) );
|
gnc_html_history_node_new( type, location, label ) );
|
||||||
load_to_stream( GNC_HTML_WEBKIT(self), type, location, label );
|
stream_loaded = load_to_stream( GNC_HTML_WEBKIT(self),
|
||||||
|
type, location, label );
|
||||||
|
|
||||||
}
|
}
|
||||||
while ( FALSE );
|
while ( FALSE );
|
||||||
@ -948,7 +969,7 @@ impl_webkit_show_url( GncHtml* self, URLType type,
|
|||||||
PERR( "URLType %s not supported.", type );
|
PERR( "URLType %s not supported.", type );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( priv->base.load_cb != NULL )
|
if ( stream_loaded && priv->base.load_cb != NULL )
|
||||||
{
|
{
|
||||||
(priv->base.load_cb)( GNC_HTML(self), type, location, label, priv->base.load_cb_data );
|
(priv->base.load_cb)( GNC_HTML(self), type, location, label, priv->base.load_cb_data );
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user