diff options
Diffstat (limited to 'embed/ephy-view-source-handler.c')
-rw-r--r-- | embed/ephy-view-source-handler.c | 172 |
1 files changed, 137 insertions, 35 deletions
diff --git a/embed/ephy-view-source-handler.c b/embed/ephy-view-source-handler.c index af6276929..fe2de7124 100644 --- a/embed/ephy-view-source-handler.c +++ b/embed/ephy-view-source-handler.c @@ -21,9 +21,12 @@ #include "config.h" #include "ephy-view-source-handler.h" +#include "ephy-embed-container.h" #include "ephy-embed-shell.h" +#include "ephy-web-view.h" #include <gio/gio.h> +#include <glib/gi18n.h> #include <string.h> struct _EphyViewSourceHandler { @@ -47,13 +50,11 @@ ephy_view_source_request_new (EphyViewSourceHandler *handler, WebKitURISchemeRequest *request) { EphyViewSourceRequest *view_source_request; - EphyEmbedShell *shell = ephy_embed_shell_get_default (); - WebKitWebContext *context = ephy_embed_shell_get_web_context (shell); view_source_request = g_slice_new (EphyViewSourceRequest); - view_source_request->source_handler = handler; + view_source_request->source_handler = g_object_ref (handler); view_source_request->scheme_request = g_object_ref (request); - view_source_request->web_view = g_object_ref_sink (webkit_web_view_new_with_context (context)); + view_source_request->web_view = NULL; /* created only if required */ view_source_request->cancellable = g_cancellable_new (); view_source_request->load_changed_id = 0; @@ -66,8 +67,9 @@ ephy_view_source_request_free (EphyViewSourceRequest *request) if (request->load_changed_id > 0) g_signal_handler_disconnect (request->web_view, request->load_changed_id); + g_object_unref (request->source_handler); g_object_unref (request->scheme_request); - g_object_unref (request->web_view); + g_clear_object (&request->web_view); g_cancellable_cancel (request->cancellable); g_object_unref (request->cancellable); @@ -77,21 +79,28 @@ ephy_view_source_request_free (EphyViewSourceRequest *request) static void finish_uri_scheme_request (EphyViewSourceRequest *request, - gchar *data) + gchar *data, + GError *error) { GInputStream *stream; gssize data_length; - data_length = MIN (strlen (data), G_MAXSSIZE); - stream = g_memory_input_stream_new_from_data (data, data_length, g_free); - webkit_uri_scheme_request_finish (request->scheme_request, stream, data_length, "text/html"); + g_assert ((data && !error) || (!data && error)); + + if (error) { + webkit_uri_scheme_request_finish_error (request->scheme_request, error); + } else { + data_length = MIN (strlen (data), G_MAXSSIZE); + stream = g_memory_input_stream_new_from_data (data, data_length, g_free); + webkit_uri_scheme_request_finish (request->scheme_request, stream, data_length, "text/html"); + g_object_unref (stream); + } request->source_handler->outstanding_requests = g_list_remove (request->source_handler->outstanding_requests, request); ephy_view_source_request_free (request); - g_object_unref (stream); } static void @@ -108,10 +117,8 @@ web_resource_data_cb (WebKitWebResource *resource, data = webkit_web_resource_get_data_finish (resource, result, &length, &error); if (error) { - html = g_strdup (error->message); - length = strlen (html); + finish_uri_scheme_request (request, NULL, error); g_error_free (error); - finish_uri_scheme_request (request, html); return; } @@ -123,15 +130,32 @@ web_resource_data_cb (WebKitWebResource *resource, escaped_str = g_markup_escape_text (data_str, -1); g_free (data_str); - html = g_strdup_printf ("<body>" - "<pre>" - "<code class=\"language-html\">%s</code>" + html = g_strdup_printf ("<head>" + "<link href=\"ephy-resource:///org/gnome/epiphany/prism.css\" rel=\"stylesheet\"/>" + "</head>" + "<body style=\"background-color: #f5f2f0;\">" + "<script src=\"ephy-resource:///org/gnome/epiphany/prism.js\"></script>" + /* http://prismjs.com/plugins/line-numbers/ */ + "<pre class=\"line-numbers\" style=\"overflow: visible\">" + "<code class=\"language-markup\">%s</code>" "</pre>" "</body>", escaped_str); g_free (escaped_str); - finish_uri_scheme_request (request, html); + finish_uri_scheme_request (request, html, NULL); +} + +static void +ephy_view_source_request_begin_get_source_from_web_view (EphyViewSourceRequest *request, + WebKitWebView *web_view) +{ + WebKitWebResource *resource = webkit_web_view_get_main_resource (web_view); + g_assert (resource); + webkit_web_resource_get_data (resource, + request->cancellable, + (GAsyncReadyCallback)(web_resource_data_cb), + request); } static void @@ -139,13 +163,79 @@ load_changed_cb (WebKitWebView *web_view, WebKitLoadEvent load_event, EphyViewSourceRequest *request) { - if (load_event == WEBKIT_LOAD_FINISHED) { - WebKitWebResource *resource = webkit_web_view_get_main_resource (web_view); - webkit_web_resource_get_data (resource, - request->cancellable, - (GAsyncReadyCallback)(web_resource_data_cb), - request); - } + if (load_event == WEBKIT_LOAD_FINISHED) + ephy_view_source_request_begin_get_source_from_web_view (request, web_view); +} + +static void +ephy_view_source_request_begin_get_source_from_uri (EphyViewSourceRequest *request, + const char *uri) +{ + EphyEmbedShell *shell = ephy_embed_shell_get_default (); + WebKitWebContext *context = ephy_embed_shell_get_web_context (shell); + + request->web_view = WEBKIT_WEB_VIEW (g_object_ref_sink (webkit_web_view_new_with_context (context))); + + g_assert (request->load_changed_id == 0); + request->load_changed_id = g_signal_connect (request->web_view, "load-changed", + G_CALLBACK (load_changed_cb), + request); + + webkit_web_view_load_uri (request->web_view, uri); +} + +static gint +embed_is_displaying_matching_uri (EphyEmbed *embed, + SoupURI *uri) +{ + EphyWebView *web_view; + SoupURI *view_uri; + gint ret = -1; + + if (ephy_embed_has_load_pending (embed)) + return -1; + + web_view = ephy_embed_get_web_view (embed); + if (ephy_web_view_is_loading (web_view)) + return -1; + + view_uri = soup_uri_new (ephy_web_view_get_address (web_view)); + if (!view_uri) + return -1; + + soup_uri_set_fragment (view_uri, NULL); + ret = soup_uri_equal (view_uri, uri) ? 0 : -1; + + soup_uri_free (view_uri); + + return ret; +} + +static WebKitWebView * +get_web_view_matching_uri (SoupURI *uri) +{ + EphyEmbedShell *shell; + GtkWindow *window; + GList *embeds = NULL; + GList *found; + EphyEmbed *embed = NULL; + + shell = ephy_embed_shell_get_default (); + window = gtk_application_get_active_window (GTK_APPLICATION (shell)); + + if (!EPHY_IS_EMBED_CONTAINER (window)) + goto out; + + embeds = ephy_embed_container_get_children (EPHY_EMBED_CONTAINER (window)); + found = g_list_find_custom (embeds, uri, (GCompareFunc)embed_is_displaying_matching_uri); + + if (found) + embed = found->data; + +out: + g_list_free (embeds); + + return embed ? WEBKIT_WEB_VIEW (ephy_embed_get_web_view (embed)) : NULL; } static void @@ -155,6 +245,7 @@ ephy_view_source_request_start (EphyViewSourceRequest *request) char *modified_uri; char *decoded_fragment; const char *original_uri; + WebKitWebView *web_view; request->source_handler->outstanding_requests = g_list_prepend (request->source_handler->outstanding_requests, request); @@ -162,25 +253,29 @@ ephy_view_source_request_start (EphyViewSourceRequest *request) original_uri = webkit_uri_scheme_request_get_uri (request->scheme_request); soup_uri = soup_uri_new (original_uri); - if (!soup_uri) { - g_critical ("Failed to construct SoupURI for %s", original_uri); - finish_uri_scheme_request (request, g_strdup ("")); + if (!soup_uri || !soup_uri->fragment) { + /* Can't assert because user could theoretically input something weird */ + GError *error = g_error_new (WEBKIT_NETWORK_ERROR, + WEBKIT_NETWORK_ERROR_FAILED, + _("%s is not a valid URI"), + original_uri); + finish_uri_scheme_request (request, NULL, error); + g_error_free (error); return; } /* Convert e.g. ephy-source://gnome.org#https to https://gnome.org */ - g_assert (soup_uri->fragment); decoded_fragment = soup_uri_decode (soup_uri->fragment); soup_uri_set_scheme (soup_uri, decoded_fragment); soup_uri_set_fragment (soup_uri, NULL); modified_uri = soup_uri_to_string (soup_uri, FALSE); + g_assert (modified_uri); - g_assert(request->load_changed_id == 0); - request->load_changed_id = g_signal_connect (request->web_view, "load-changed", - G_CALLBACK (load_changed_cb), - request); - - webkit_web_view_load_uri (request->web_view, modified_uri); + web_view = get_web_view_matching_uri (soup_uri); + if (web_view) + ephy_view_source_request_begin_get_source_from_web_view (request, WEBKIT_WEB_VIEW (web_view)); + else + ephy_view_source_request_begin_get_source_from_uri (request, modified_uri); g_free (decoded_fragment); g_free (modified_uri); @@ -188,12 +283,19 @@ ephy_view_source_request_start (EphyViewSourceRequest *request) } static void +cancel_outstanding_request (EphyViewSourceRequest *request) +{ + g_cancellable_cancel (request->cancellable); +} + +static void ephy_view_source_handler_dispose (GObject *object) { EphyViewSourceHandler *handler = EPHY_VIEW_SOURCE_HANDLER (object); if (handler->outstanding_requests) { - g_list_free_full (handler->outstanding_requests, (GDestroyNotify)ephy_view_source_request_free); + g_list_foreach (handler->outstanding_requests, (GFunc)cancel_outstanding_request, NULL); + g_list_free (handler->outstanding_requests); handler->outstanding_requests = NULL; } |