aboutsummaryrefslogtreecommitdiffstats
path: root/embed/mozilla/EphyAboutModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'embed/mozilla/EphyAboutModule.cpp')
-rw-r--r--embed/mozilla/EphyAboutModule.cpp520
1 files changed, 520 insertions, 0 deletions
diff --git a/embed/mozilla/EphyAboutModule.cpp b/embed/mozilla/EphyAboutModule.cpp
new file mode 100644
index 000000000..f6247eec3
--- /dev/null
+++ b/embed/mozilla/EphyAboutModule.cpp
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2001 Matt Aubury, Philip Langdale
+ * Copyright (C) 2004 Crispin Flowerday
+ * Copyright (C) 2005 Christian Persch
+ * Copyright (C) 2005 Adam Hooper
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include "mozilla-config.h"
+
+#include "config.h"
+
+#include <nsCOMPtr.h>
+#include <nsIIOService.h>
+#include <nsIServiceManager.h>
+#include <nsIURI.h>
+#include <nsIChannel.h>
+#include <nsIOutputStream.h>
+#include <nsIInputStream.h>
+#include <nsIStorageStream.h>
+#include <nsIInputStreamChannel.h>
+#include <nsIScriptSecurityManager.h>
+#include <nsNetCID.h>
+#include <nsString.h>
+#include <nsEscape.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "EphyAboutModule.h"
+#include "EphyUtils.h"
+
+#include "ephy-debug.h"
+
+#include <string.h>
+
+EphyAboutModule::EphyAboutModule()
+{
+ LOG ("EphyAboutModule ctor [%p]\n", this);
+}
+
+EphyAboutModule::~EphyAboutModule()
+{
+ LOG ("EphyAboutModule dtor [%p]\n", this);
+}
+
+NS_IMPL_ISUPPORTS1 (EphyAboutModule, nsIAboutModule)
+
+/* nsIChannel newChannel (in nsIURI aURI); */
+NS_IMETHODIMP
+EphyAboutModule::NewChannel(nsIURI *aURI,
+ nsIChannel **_retval)
+{
+ NS_ENSURE_ARG(aURI);
+
+ nsCAutoString path;
+ aURI->GetPath (path);
+
+ if (strncmp (path.get(), "neterror", strlen ("neterror")) == 0)
+ {
+ return CreateErrorPage (aURI, _retval);
+ }
+
+ if (strncmp (path.get (), "epiphany", strlen ("epiphany")) == 0)
+ {
+ return Redirect (nsDependentCString ("file://" SHARE_DIR "/epiphany.xhtml"), _retval);
+ }
+
+ return NS_ERROR_ILLEGAL_VALUE;
+}
+
+/* private functions */
+
+nsresult
+EphyAboutModule::Redirect(const nsACString &aURL,
+ nsIChannel **_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIIOService> ioService;
+ rv = EphyUtils::GetIOService (getter_AddRefs (ioService));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIChannel> tempChannel;
+ rv = ioService->NewChannel(aURL, nsnull, nsnull, getter_AddRefs(tempChannel));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIURI> uri;
+ rv = ioService->NewURI(aURL, nsnull, nsnull, getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ tempChannel->SetOriginalURI (uri);
+
+ nsCOMPtr<nsIScriptSecurityManager> securityManager =
+ do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIPrincipal> principal;
+ rv = securityManager->GetCodebasePrincipal(uri, getter_AddRefs(principal));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = tempChannel->SetOwner(principal);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ NS_ADDREF(*_retval = tempChannel);
+ return rv;
+}
+
+nsresult
+EphyAboutModule::ParseErrorURL(const char *aURL,
+ nsACString &aError,
+ nsACString &aRawOriginURL,
+ nsACString &aOriginURL,
+ nsACString &aOriginCharset)
+{
+ /* The error page URL is of the form "epiphany:error?e=<error>&u=<URL>&c=<charset>&d=<description>" */
+ const char *query = strstr (aURL, "?");
+ if (!query) return NS_ERROR_FAILURE;
+
+ /* skip the '?' */
+ ++query;
+
+ char **params = g_strsplit (query, "&", -1);
+ if (!params) return NS_ERROR_FAILURE;
+
+ for (PRUint32 i = 0; params[i] != NULL; ++i)
+ {
+ char *param = params[i];
+
+ if (strlen (param) <= 2) continue;
+
+ switch (param[0])
+ {
+ case 'e':
+ aError.Assign (nsUnescape (param + 2));
+ break;
+ case 'u':
+ aRawOriginURL.Assign (param + 2);
+ aOriginURL.Assign (nsUnescape (param + 2));
+ break;
+ case 'c':
+ aOriginCharset.Assign (nsUnescape (param + 2));
+ break;
+ case 'd':
+ /* we don't need mozilla's description parameter */
+ default:
+ break;
+ }
+ }
+
+ g_strfreev (params);
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::GetErrorMessage(nsIURI *aURI,
+ const char *aError,
+ char **aPrimary,
+ char **aSecondary,
+ char **aTertiary,
+ char **aLinkIntro)
+{
+ if (strcmp (aError, "protocolNotFound") == 0)
+ {
+ nsCAutoString scheme;
+ aURI->GetScheme (scheme);
+
+ /* Translators: %s is the name of a protocol, like "http" etc. */
+ *aPrimary = g_strdup_printf (_("“%s” protocol is not supported."), scheme.get());
+ /* FIXME: get the list of supported protocols from necko */
+ *aSecondary = _("Supported protocols are “http”, “https”, “ftp”, “file”, “smb” "
+ "and “sftp”.");
+ }
+ else if (strcmp (aError, "fileNotFound") == 0)
+ {
+ nsCAutoString path;
+ aURI->GetPath (path);
+
+ /* Translators: %s is the path and filename, for example "/home/user/test.html" */
+ *aPrimary = g_markup_printf_escaped (_("File “%s” not found."), path.get());
+ *aSecondary = _("Check the location of the file and try again.");
+ }
+ else if (strcmp (aError, "dnsNotFound") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped (_("“%s” could not be found."),
+ host.get());
+ *aSecondary = _("Check that you are connected to the internet, and "
+ "that the address is correct.");
+ *aLinkIntro = _("If this page used to exist, you may find an archived version:");
+ }
+ else if (strcmp (aError, "connectionFailure") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” refused the connection."),
+ host.get());
+ *aSecondary = _("The server may be busy or you may have a "
+ "network connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "netInterrupt") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” interrupted the connection."),
+ host.get());
+ *aSecondary = _("The server may be busy or you may have a "
+ "network connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "netTimeout") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” is not responding."),
+ host.get());
+ *aSecondary = _("The connection was lost because the "
+ "server took too long to respond.");
+ *aTertiary = _("The server may be busy or you may have a network "
+ "connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "malformedURI") == 0)
+ {
+ *aPrimary = g_strdup (_("Invalid address."));
+ *aSecondary = g_strdup (_("The address you entered is not valid."));
+ }
+ else if (strcmp (aError, "redirectLoop") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” redirected too many times."),
+ host.get());
+ *aSecondary = _("The redirection has been stopped for security reasons.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "unknownSocketType") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” requires an encrypted connection."),
+ host.get());
+ *aSecondary = _("The document could not be loaded because "
+ "encryption support is not installed.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "netReset") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” dropped the connection."),
+ host.get());
+ *aSecondary = _("The server dropped the connection "
+ "before any data could be read.");
+ *aTertiary = _("The server may be busy or you may have a "
+ "network connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "netOffline") == 0)
+ {
+ *aPrimary = g_strdup (_("Cannot load document in offline mode."));
+ *aSecondary = _("This document cannot be viewed in offline "
+ "mode. Set Epiphany to “online” "
+ "and try again.");
+ }
+ else if (strcmp (aError, "deniedPortAccess") == 0)
+ {
+ nsCAutoString host;
+ aURI->GetHost (host);
+
+ PRInt32 port = -1;
+ aURI->GetPort (&port);
+
+ /* Translators: %s is the hostname, like "www.example.com" */
+ *aPrimary = g_markup_printf_escaped
+ (_("“%s” denied access to port “%d”."),
+ host.get(), port > 0 ? port : 80);
+ *aSecondary = g_strdup (_("The server dropped the connection "
+ "before any data could be read."));
+ *aTertiary = _("The server may be busy or you may have a "
+ "network connection problem. Try again later.");
+ *aLinkIntro = _("There may be an old version of the page you wanted:");
+ }
+ else if (strcmp (aError, "proxyResolveFailure") == 0 ||
+ strcmp (aError, "proxyConnectFailure") == 0)
+ {
+ *aPrimary = g_strdup (_("Could not connect to proxy server."));
+ *aSecondary = _("Check the proxy server settings in Control Center. "
+ "If the connection still fails, there may be "
+ "a problem with your proxy server or your "
+ "network connection.");
+ }
+ else
+ {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+EphyAboutModule::CreateErrorPage(nsIURI *aErrorURI,
+ nsIChannel **_retval)
+{
+ /* First parse the arguments */
+ nsresult rv = NS_ERROR_ILLEGAL_VALUE;
+ nsCAutoString spec;
+ rv = aErrorURI->GetSpec (spec);
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && !spec.IsEmpty(), rv);
+
+ nsCAutoString error, rawurl, url, charset;
+ rv = ParseErrorURL (spec.get (), error, rawurl, url, charset);
+ if (NS_FAILED (rv) || error.IsEmpty () || url.IsEmpty()) return rv;
+
+ nsCOMPtr<nsIURI> uri;
+ rv = EphyUtils::NewURI(getter_AddRefs (uri), url, charset.get());
+ /* FIXME can uri be NULL if the original url was invalid? */
+ NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && uri, rv);
+
+ char *primary = nsnull, *secondary = nsnull, *tertiary = nsnull, *linkintro = nsnull;
+ rv = GetErrorMessage (uri, error.get(), &primary, &secondary, &tertiary, &linkintro);
+
+ /* we don't know about this error code.
+ * FIXME: We'd like to forward to mozilla's about:neterror handler,
+ * but I don't know how to. So just redirect to the same page that
+ * mozilla's handler redirects to.
+ */
+ if (rv == NS_ERROR_ILLEGAL_VALUE)
+ {
+ nsCAutoString url(spec);
+
+ /* remove "about:neterror" part and insert mozilla's error page url */
+ url.Cut(0, strlen ("about:neterror"));
+ url.Insert("chrome://global/content/netError.xhtml", 0);
+
+ return Redirect (url, _retval);
+ }
+
+ NS_ENSURE_TRUE (primary && secondary, NS_ERROR_FAILURE);
+
+ /* open the rendering stream */
+ nsCOMPtr<nsIStorageStream> storageStream;
+ rv = NS_NewStorageStream(16384, (PRUint32) -1, getter_AddRefs (storageStream));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIOutputStream> stream;
+ rv = storageStream->GetOutputStream(0, getter_AddRefs (stream));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ char *language = g_strdup (pango_language_to_string (gtk_get_default_language ()));
+ g_strdelimit (language, "_-@", '\0');
+
+ Write (stream,
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"");
+ Write (stream, language);
+ Write (stream,
+ "\" xml:lang=\"");
+ Write (stream, language);
+ Write (stream,
+ "\">\n"
+ "<head>\n"
+ "<title>");
+ Write (stream, primary);
+ /* no favicon for now, it would pollute the favicon cache */
+ /* "<link rel=\"icon\" type=\"image/png\" href=\"moz-icon://stock/gtk-dialog-error?size=16\" />\n" */
+ Write (stream,
+ "</title>\n"
+ "<style type=\"text/css\">\n"
+ "div#body {\n"
+ "top: 12px;\n"
+ "right: 12px;\n"
+ "bottom: 12px;\n"
+ "left: 12px;\n"
+ "overflow: auto;\n"
+
+ "background: -moz-dialog url('moz-icon://stock/gtk-dialog-error?size=dialog') no-repeat 12px 12px;\n"
+ "color: -moz-dialogtext;\n"
+ "font: message-box;\n"
+ "border: 1px solid -moz-dialogtext;\n"
+
+ "padding: 12px 12px 12px 72px;\n"
+ "}\n"
+
+ "h1 {\n"
+ "margin: 0;\n"
+ "font-size: 1.2em;\n"
+ "}\n"
+ "</style>\n"
+ "</head>\n"
+ "<body dir=\"");
+ Write (stream,
+ gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL ? "rtl" : "ltr");
+ Write (stream,
+ "\">\n"
+ "<div id=\"body\">"
+ "<h1>");
+ Write (stream, primary);
+ Write (stream,
+ "</h1>\n"
+ "<p>");
+ Write (stream, secondary);
+ if (tertiary)
+ {
+ Write (stream, " ");
+ Write (stream, tertiary);
+ }
+ Write (stream,
+ "</p>\n");
+
+ PRBool isHttp = PR_FALSE, isHttps = PR_FALSE;
+ uri->SchemeIs ("http", &isHttp);
+ uri->SchemeIs ("https", &isHttps);
+ if (linkintro && (isHttp || isHttps))
+ {
+ Write (stream, "<p>");
+ Write (stream, linkintro);
+ Write (stream, "<ul>\n");
+ Write (stream, "<li><a href=\"http://google.com/search?q=cache:");
+ Write (stream, rawurl.get());
+ Write (stream, "\">");
+ /* Translators: The text before the "|" is context to help you decide on
+ * the correct translation. You MUST OMIT it in the translated string. */
+ Write (stream, Q_("You may find an old version:|in the Google Cache"));
+ Write (stream, "</a></li>\n");
+
+ Write (stream, "<li><a href=\"http://web.archive.org/web/*/");
+ Write (stream, rawurl.get());
+ Write (stream, "\">");
+ /* Translators: The text before the "|" is context to help you decide on
+ * the correct translation. You MUST OMIT it in the translated string. */
+ Write (stream, Q_("You may find an old version:|in the Internet Archive"));
+ Write (stream, "</a></li>\n"
+ "</ul>\n"
+ "</p>");
+ }
+
+ Write (stream,
+ "</div>\n"
+ "</body>\n"
+ "</html>\n");
+
+ g_free (language);
+ g_free (primary);
+
+ /* finish the rendering */
+ nsCOMPtr<nsIInputStream> inputStream;
+ rv = storageStream->NewInputStream(0, getter_AddRefs (inputStream));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIInputStreamChannel> channel (do_CreateInstance ("@mozilla.org/network/input-stream-channel;1", &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv |= channel->SetURI (aErrorURI);
+ rv |= channel->SetContentStream (inputStream);
+ rv |= channel->SetContentType (NS_LITERAL_CSTRING ("application/xhtml+xml"));
+ rv |= channel->SetContentCharset (NS_LITERAL_CSTRING ("utf-8"));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIScriptSecurityManager> securityManager
+ (do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ nsCOMPtr<nsIPrincipal> principal;
+ rv = securityManager->GetCodebasePrincipal (aErrorURI, getter_AddRefs (principal));
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ rv = channel->SetOwner(principal);
+ NS_ENSURE_SUCCESS (rv, rv);
+
+ NS_ADDREF(*_retval = channel);
+ return rv;
+}
+
+nsresult
+EphyAboutModule::Write(nsIOutputStream *aStream,
+ const char *aText)
+{
+ PRUint32 bytesWritten;
+ return aStream->Write (aText, strlen (aText), &bytesWritten);
+}