[epiphany] Added about:plugins support.



commit 89cd6749b82686ca78e8d44c5b3fb18fead02363
Author: Sergio Villar Senin <svillar igalia com>
Date:   Wed Mar 30 09:36:08 2011 +0200

    Added about:plugins support.
    
    We are now able to show a page with the list of installed plugins.
    
    Bug #575498

 data/pages/Makefile.am            |    6 +-
 data/pages/about.css              |   31 ++++++++
 embed/ephy-embed-single.c         |    9 ++
 embed/ephy-embed-utils.c          |   19 ++++-
 embed/ephy-history.c              |   12 +++-
 embed/ephy-web-view.c             |    8 ++
 lib/Makefile.am                   |    4 +-
 lib/ephy-request-about.c          |  149 +++++++++++++++++++++++++++++++++++++
 lib/ephy-request-about.h          |   37 +++++++++
 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 f2b879a..5062f09 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 0000000..2937047
--- /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 2353a12..a214f82 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 d0e3690..2ca6d76 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 86a4aaa..b6fe5dc 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 64ddc69..8cd73a7 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 6be8ef7..63d58db 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 0000000..167f2ec
--- /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 0000000..bb16eda
--- /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 79c921f..cb8d9b3 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 */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]