diff options
-rw-r--r-- | data/pages/Makefile.am | 6 | ||||
-rw-r--r-- | data/pages/about.css | 31 | ||||
-rw-r--r-- | embed/ephy-embed-single.c | 9 | ||||
-rw-r--r-- | embed/ephy-embed-utils.c | 19 | ||||
-rw-r--r-- | embed/ephy-history.c | 12 | ||||
-rw-r--r-- | embed/ephy-web-view.c | 8 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/ephy-request-about.c | 149 | ||||
-rw-r--r-- | lib/ephy-request-about.h | 37 | ||||
-rw-r--r-- | lib/widgets/ephy-location-entry.c | 17 |
10 files changed, 282 insertions, 10 deletions
diff --git a/data/pages/Makefile.am b/data/pages/Makefile.am index f2b879a5f..5062f0989 100644 --- a/data/pages/Makefile.am +++ b/data/pages/Makefile.am @@ -3,4 +3,8 @@ errorpages_DATA = \ recovery.html \ error.html -EXTRA_DIST = $(errorpages_DATA) +stylepagesdir = $(pkgdatadir)/pages +stylepages_DATA = \ + about.css + +EXTRA_DIST = $(errorpages_DATA) $(stylepages_DATA) diff --git a/data/pages/about.css b/data/pages/about.css new file mode 100644 index 000000000..2937047eb --- /dev/null +++ b/data/pages/about.css @@ -0,0 +1,31 @@ +#plugin-table +{ + margin: 14px; + width: 80%; + text-align: left; + border-collapse: collapse; +} + +#plugin-table th +{ + padding: 8px; + background:#b9c9ff; + border-top: 4px solid #aabcff; + border-bottom: 1px solid #fff; + color: #039; +} + +#plugin-table td +{ + padding: 8px; + background: #e8edff; + border-bottom: 1px solid #fff; + color: #669; + border-top: 1px solidtransparent; +} + +#plugin-table tr:hover td +{ + background: #d0dafd; + color:#339; +}
\ No newline at end of file diff --git a/embed/ephy-embed-single.c b/embed/ephy-embed-single.c index 2353a122b..a214f82bd 100644 --- a/embed/ephy-embed-single.c +++ b/embed/ephy-embed-single.c @@ -36,6 +36,7 @@ #include "ephy-profile-utils.h" #include "ephy-prefs.h" #include "ephy-settings.h" +#include "ephy-request-about.h" #ifdef ENABLE_CERTIFICATE_MANAGER #include "ephy-certificate-manager.h" @@ -45,6 +46,7 @@ #include <glib/gi18n.h> #include <libsoup/soup-gnome.h> #include <libsoup/soup-cache.h> +#include <libsoup/soup-requester.h> #include <gnome-keyring.h> #define EPHY_EMBED_SINGLE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_EMBED_SINGLE, EphyEmbedSinglePrivate)) @@ -484,6 +486,7 @@ ephy_embed_single_initialize (EphyEmbedSingle *single) char *cookie_policy; char *cache_dir; EphyEmbedSinglePrivate *priv = single->priv; + SoupSessionFeature *requester; /* Initialise nspluginwrapper's plugins if available */ if (g_file_test (NSPLUGINWRAPPER_SETUP, G_FILE_TEST_EXISTS) != FALSE) @@ -537,6 +540,12 @@ ephy_embed_single_initialize (EphyEmbedSingle *single) G_CALLBACK (cache_size_cb), single); + /* about: URIs handler */ + requester = SOUP_SESSION_FEATURE (soup_requester_new()); + soup_session_add_feature (session, requester); + soup_session_feature_add_feature (requester, EPHY_TYPE_REQUEST_ABOUT); + g_object_unref (requester); + #ifdef SOUP_TYPE_PASSWORD_MANAGER /* Use GNOME keyring to store passwords. Only add the manager if we are not using a private session, otherwise we want any new diff --git a/embed/ephy-embed-utils.c b/embed/ephy-embed-utils.c index d0e369052..2ca6d7689 100644 --- a/embed/ephy-embed-utils.c +++ b/embed/ephy-embed-utils.c @@ -29,6 +29,7 @@ #include "ephy-string.h" #include "ephy-embed-utils.h" +#include "ephy-request-about.h" char* ephy_embed_utils_link_message_parse (char *message) @@ -105,15 +106,25 @@ ephy_embed_utils_address_has_web_scheme (const char *address) char* ephy_embed_utils_normalize_address (const char *address) { - char *effective_address; + char *effective_address = NULL; g_return_val_if_fail (address, NULL); if (ephy_embed_utils_address_has_web_scheme (address) == FALSE) effective_address = g_strconcat ("http://", address, NULL); - else - effective_address = g_strdup (address); - + else { + /* Convert about: schemes to ephy-about: in order to + * force WebKit to delegate its handling to our + * EphyRequestAbout. In general about: schemes are + * handled internally by WebKit and mean "empty + * document". + */ + if (!g_ascii_strcasecmp (address, "about:plugins")) + effective_address = g_strdup (EPHY_ABOUT_SCHEME":plugins"); + else + effective_address = g_strdup (address); + } + return effective_address; } diff --git a/embed/ephy-history.c b/embed/ephy-history.c index 86a4aaaf0..b6fe5dc4b 100644 --- a/embed/ephy-history.c +++ b/embed/ephy-history.c @@ -27,6 +27,7 @@ #include "ephy-node-db.h" #include "ephy-node-common.h" #include "ephy-prefs.h" +#include "ephy-request-about.h" #include "ephy-settings.h" #include "ephy-string.h" @@ -823,22 +824,30 @@ ephy_history_add_page (EphyHistory *eh, static gboolean impl_add_page (EphyHistory *eb, - const char *url, + const char *orig_url, gboolean redirect, gboolean toplevel) { EphyNode *bm, *node, *host; gulong flags = 0; + char *url; if (eb->priv->enabled == FALSE) { return FALSE; } + /* Do not show internal ephy-about: protocol to users */ + if (g_str_has_prefix (orig_url, EPHY_ABOUT_SCHEME)) + url = g_strdup_printf ("about:%s", orig_url + EPHY_ABOUT_SCHEME_LEN + 1); + else + url = g_strdup (orig_url); + node = ephy_history_get_page (eb, url); if (node) { ephy_history_visited (eb, node); + g_free (url); return TRUE; } @@ -846,6 +855,7 @@ impl_add_page (EphyHistory *eb, ephy_node_set_property_string (bm, EPHY_NODE_PAGE_PROP_LOCATION, url); ephy_node_set_property_string (bm, EPHY_NODE_PAGE_PROP_TITLE, url); + g_free (url); if (redirect) flags |= REDIRECT_FLAG; if (toplevel) flags |= TOPLEVEL_FLAG; diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c index 64ddc69a9..8cd73a769 100644 --- a/embed/ephy-web-view.c +++ b/embed/ephy-web-view.c @@ -44,6 +44,7 @@ #include "ephy-profile-utils.h" #include "ephy-favicon-cache.h" #include "ephy-history.h" +#include "ephy-request-about.h" #include "ephy-settings.h" #include "ephy-string.h" #include "ephy-web-view.h" @@ -2455,6 +2456,8 @@ get_title_from_address (const char *address) { if (g_str_has_prefix (address, "file://")) return g_strdup (address + 7); + else if (!strcmp (address, EPHY_ABOUT_SCHEME":plugins")) + return g_strdup (_("Plugins")); else return ephy_string_get_host_name (address); } @@ -2744,6 +2747,11 @@ ephy_web_view_location_changed (EphyWebView *view, strcmp (location, "about:blank") == 0) { ephy_web_view_set_address (view, NULL); ephy_web_view_set_title (view, EMPTY_PAGE); + } else if (g_str_has_prefix (location, EPHY_ABOUT_SCHEME)) { + char *new_address = g_strdup_printf ("about:%s", location + EPHY_ABOUT_SCHEME_LEN + 1); + ephy_web_view_set_address (view, new_address); + g_free (new_address); + ephy_web_view_set_title (view, EMPTY_PAGE); } else { char *view_address; diff --git a/lib/Makefile.am b/lib/Makefile.am index 6be8ef745..63d58db1e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -19,8 +19,9 @@ NOINST_H_FILES = \ ephy-node-common.h \ ephy-object-helpers.h \ ephy-prefs.h \ - ephy-profile-utils.h \ + ephy-profile-utils.h \ ephy-print-utils.h \ + ephy-request-about.h \ ephy-shlib-loader.h \ ephy-signal-accumulator.h \ ephy-string.h \ @@ -60,6 +61,7 @@ libephymisc_la_SOURCES = \ ephy-profile-utils.c \ ephy-profile-utils.h \ ephy-print-utils.c \ + ephy-request-about.c \ ephy-settings.c \ ephy-shlib-loader.c \ ephy-signal-accumulator.c \ diff --git a/lib/ephy-request-about.c b/lib/ephy-request-about.c new file mode 100644 index 000000000..167f2ec27 --- /dev/null +++ b/lib/ephy-request-about.c @@ -0,0 +1,149 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * ephy-request-about.c: about: URI request object + * + * Copyright (C) 2011, Igalia S.L. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gio/gio.h> +#include <glib/gi18n.h> +#include <libsoup/soup-uri.h> +#include <webkit/webkit.h> + +#include "ephy-file-helpers.h" +#include "ephy-request-about.h" + +G_DEFINE_TYPE (EphyRequestAbout, ephy_request_about, SOUP_TYPE_REQUEST) + +struct _EphyRequestAboutPrivate { + gssize content_length; + gchar *css_style; +}; + +static void +ephy_request_about_init (EphyRequestAbout *about) +{ + about->priv = G_TYPE_INSTANCE_GET_PRIVATE (about, EPHY_TYPE_REQUEST_ABOUT, EphyRequestAboutPrivate); + about->priv->content_length = 0; + about->priv->css_style = NULL; +} + +static void +ephy_request_about_finalize (GObject *obj) +{ + g_free (EPHY_REQUEST_ABOUT(obj)->priv->css_style); + + G_OBJECT_CLASS (ephy_request_about_parent_class)->finalize (obj); +} + +static gboolean +ephy_request_about_check_uri (SoupRequest *request, + SoupURI *uri, + GError **error) +{ + return uri->host == NULL; +} + +static void +read_css_style (EphyRequestAbout *about) +{ + GError *error = NULL; + + if (!g_file_get_contents (ephy_file("about.css"), &(about->priv->css_style), NULL, &error)) + g_debug (error->message); +} + +static GInputStream * +ephy_request_about_send (SoupRequest *request, + GCancellable *cancellable, + GError **error) +{ + EphyRequestAbout *about = EPHY_REQUEST_ABOUT (request); + SoupURI *uri = soup_request_get_uri (request); + GString *data_str = g_string_new("<html>"); + + if (!about->priv->css_style) + read_css_style (about); + + g_string_append_printf (data_str, "<head><title>%s</title>" \ + "<style type=\"text/css\">%s</style></head><body>", + _("Installed plugins"), + about->priv->css_style); + + if (!g_strcmp0 (uri->path, "plugins")) { + WebKitWebPluginDatabase* database = webkit_get_web_plugin_database (); + GSList *plugin_list, *p; + + g_string_append_printf(data_str, "<h1>%s</h1>", _("Installed plugins")); + plugin_list = webkit_web_plugin_database_get_plugins (database); + for (p = plugin_list; p; p = p->next) { + WebKitWebPlugin *plugin = WEBKIT_WEB_PLUGIN (p->data); + GSList *m, *mime_types; + + g_string_append_printf(data_str, "<h2>%s</h2>%s<br>%s: <b>%s</b>"\ + "<table id=\"plugin-table\">" \ + "<thead><tr><th>%s</th><th>%s</th><th>%s</th></tr></thead><tbody>", + webkit_web_plugin_get_name (plugin), + webkit_web_plugin_get_description (plugin), + _("Enabled"), webkit_web_plugin_get_enabled (plugin) ? _("Yes") : _("No"), + _("MIME type"), _("Description"), _("Suffixes")); + + mime_types = webkit_web_plugin_get_mimetypes (plugin); + for (m = mime_types; m; m = m->next) { + WebKitWebPluginMIMEType *mime_type = (WebKitWebPluginMIMEType*) m->data; + guint extensions_len = g_strv_length (mime_type->extensions); + guint i; + + g_string_append_printf (data_str, "<tr><td>%s</td><td>%s</td><td>", + mime_type->name, mime_type->description); + + for (i = 0; i < extensions_len; i++) + g_string_append_printf (data_str, "%s%c", mime_type->extensions[i], + i == (extensions_len - 1) ? ' ' : ','); + + g_string_append(data_str, "</td></tr>"); + } + g_string_append(data_str, "</tbody></table>"); + } + webkit_web_plugin_database_plugins_list_free (plugin_list); + } + + g_string_append(data_str, "</body></html>"); + about->priv->content_length = data_str->len; + return g_memory_input_stream_new_from_data (g_string_free(data_str, false), about->priv->content_length, g_free); +} + +static goffset +ephy_request_about_get_content_length (SoupRequest *request) +{ + return EPHY_REQUEST_ABOUT (request)->priv->content_length; +} + +static const char * +ephy_request_about_get_content_type (SoupRequest *request) +{ + return "text/html"; +} + +static const char *about_schemes[] = { EPHY_ABOUT_SCHEME, NULL }; + +static void +ephy_request_about_class_init (EphyRequestAboutClass *request_about_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (request_about_class); + SoupRequestClass *request_class = SOUP_REQUEST_CLASS (request_about_class); + + gobject_class->finalize = ephy_request_about_finalize; + + request_class->schemes = about_schemes; + request_class->check_uri = ephy_request_about_check_uri; + request_class->send = ephy_request_about_send; + request_class->get_content_length = ephy_request_about_get_content_length; + request_class->get_content_type = ephy_request_about_get_content_type; + + g_type_class_add_private (request_about_class, sizeof (EphyRequestAboutPrivate)); +} diff --git a/lib/ephy-request-about.h b/lib/ephy-request-about.h new file mode 100644 index 000000000..bb16eda80 --- /dev/null +++ b/lib/ephy-request-about.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2011, Igalia S.L. + */ + +#ifndef EPHY_REQUEST_ABOUT_H +#define EPHY_REQUEST_ABOUT_H 1 + +#define LIBSOUP_USE_UNSTABLE_REQUEST_API +#include <libsoup/soup-request.h> + +#define EPHY_TYPE_REQUEST_ABOUT (ephy_request_about_get_type ()) +#define EPHY_REQUEST_ABOUT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EPHY_TYPE_REQUEST_ABOUT, EphyRequestAbout)) +#define EPHY_REQUEST_ABOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_REQUEST_ABOUT, EphyRequestAboutClass)) +#define EPHY_IS_REQUEST_ABOUT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EPHY_TYPE_REQUEST_ABOUT)) +#define EPHY_IS_REQUEST_ABOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EPHY_TYPE_REQUEST_ABOUT)) +#define EPHY_REQUEST_ABOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EPHY_TYPE_REQUEST_ABOUT, EphyRequestAboutClass)) + +#define EPHY_ABOUT_SCHEME "ephy-about" +#define EPHY_ABOUT_SCHEME_LEN 10 + +typedef struct _EphyRequestAboutPrivate EphyRequestAboutPrivate; + +typedef struct { + SoupRequest parent; + + EphyRequestAboutPrivate *priv; +} EphyRequestAbout; + +typedef struct { + SoupRequestClass parent; + +} EphyRequestAboutClass; + +GType ephy_request_about_get_type (void); + +#endif /* EPHY_REQUEST_ABOUT_H */ diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c index 79c921fcb..cb8d9b363 100644 --- a/lib/widgets/ephy-location-entry.c +++ b/lib/widgets/ephy-location-entry.c @@ -32,6 +32,7 @@ #include "ephy-stock-icons.h" #include "ephy-debug.h" #include "ephy-gui.h" +#include "ephy-request-about.h" #include <glib/gi18n.h> #include <gdk/gdkkeysyms.h> @@ -1049,6 +1050,12 @@ textcell_data_func (GtkCellLayout *cell_layout, if (url) { + /* Do not show internal ephy-about: protocol to users */ + if (g_str_has_prefix (url, EPHY_ABOUT_SCHEME)) { + g_free (url); + url = g_strdup_printf ("about:%s", url + strlen (EPHY_ABOUT_SCHEME) + 1); + } + ctext = g_strdup_printf ("%s\n%s", title, url); style = gtk_widget_get_style_context (priv->entry); @@ -1278,7 +1285,7 @@ ephy_location_entry_set_location (EphyLocationEntry *entry, EphyLocationEntryPrivate *priv = entry->priv; GtkClipboard *clipboard; const char *text; - char* selection = NULL; + char *effective_text = NULL, *selection = NULL; int start, end; /* Setting a new text will clear the clipboard. This makes it impossible @@ -1303,6 +1310,9 @@ ephy_location_entry_set_location (EphyLocationEntry *entry, if (address != NULL && strcmp (address, "about:blank") != 0) { + if (g_str_has_prefix (address, EPHY_ABOUT_SCHEME)) + effective_text = g_strdup_printf ("about:%s", + address + strlen (EPHY_ABOUT_SCHEME) + 1); text = address; } else @@ -1311,11 +1321,12 @@ ephy_location_entry_set_location (EphyLocationEntry *entry, } /* First record the new hash, then update the entry text */ - priv->hash = g_str_hash (text); + priv->hash = g_str_hash (effective_text ? effective_text : text); priv->block_update = TRUE; - gtk_entry_set_text (GTK_ENTRY (priv->entry), text); + gtk_entry_set_text (GTK_ENTRY (priv->entry), effective_text ? effective_text : text); priv->block_update = FALSE; + g_free (effective_text); /* We need to call update_address_state() here, as the 'changed' signal * may not get called if the user has typed in the exact correct url */ |