summaryrefslogtreecommitdiffstats
path: root/src/schemes
diff options
context:
space:
mode:
authorPatrick McDermott <pj@pehjota.net>2017-11-01 12:36:03 (EDT)
committer Patrick McDermott <pj@pehjota.net>2017-11-01 12:36:03 (EDT)
commit70fa295f32b86a6f575320665fd4541b5d969098 (patch)
tree0a7d091362c3e3028cbd4961da73df8208467d70 /src/schemes
parentf735fa8b547993130d7b5bad10e8e7e0efe61e70 (diff)
downloadmarquee-70fa295f32b86a6f575320665fd4541b5d969098.zip
marquee-70fa295f32b86a6f575320665fd4541b5d969098.tar.gz
marquee-70fa295f32b86a6f575320665fd4541b5d969098.tar.bz2
src/about*, src/view-source.*: Move under src/schemes/
Diffstat (limited to 'src/schemes')
-rw-r--r--src/schemes/about.c90
-rw-r--r--src/schemes/about.h39
-rw-r--r--src/schemes/about/local.mk4
-rw-r--r--src/schemes/about/marquee.c74
-rw-r--r--src/schemes/about/paths.h41
-rw-r--r--src/schemes/about/preferences.c260
-rw-r--r--src/schemes/about/version.c73
-rw-r--r--src/schemes/view-source.c150
-rw-r--r--src/schemes/view-source.h34
9 files changed, 765 insertions, 0 deletions
diff --git a/src/schemes/about.c b/src/schemes/about.c
new file mode 100644
index 0000000..49104a7
--- /dev/null
+++ b/src/schemes/about.c
@@ -0,0 +1,90 @@
+/*
+ * about: URI scheme
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "about.h"
+
+#include <string.h>
+
+#include <webkit2/webkit2.h>
+
+#include "../application.h"
+#include "../utils/resources.h"
+#include "../utils/string.h"
+#include "about/paths.h"
+
+void
+mq_about_request(WebKitURISchemeRequest *request, MqApplication *application)
+{
+ const gchar *path;
+ gchar *query_str;
+ GHashTable *query;
+
+ path = webkit_uri_scheme_request_get_path(request);
+ query_str = strchr(webkit_uri_scheme_request_get_uri(request), '?');
+ if (query_str && query_str[1]) {
+ query_str = g_strdup(query_str + 1);
+ query = mq_parse_query_string(query_str);
+ g_free(query_str);
+ } else {
+ query = NULL;
+ }
+
+ if (g_strcmp0(path, "") == 0 || g_strcmp0(path, "version") == 0) {
+ mq_about_version_response(application, query, request);
+ } else if (g_strcmp0(path, "preferences") == 0) {
+ mq_about_preferences_response(application, query, request);
+ } else if (g_strcmp0(path, "marquee") == 0) {
+ mq_about_marquee_response(application, query, request);
+ } else if (g_str_has_prefix(path, "resources/")) {
+ mq_resource_response(application, path + sizeof("resources"),
+ request);
+ } else {
+ return;
+ }
+
+ if (query) {
+ g_hash_table_unref(query);
+ }
+}
+
+void
+mq_about_response(WebKitURISchemeRequest *request, gchar *contents)
+{
+ gsize stream_length;
+ GInputStream *stream;
+
+ stream_length = strlen(contents);
+ stream = g_memory_input_stream_new_from_data(contents,
+ stream_length, g_free);
+ webkit_uri_scheme_request_finish(request, stream, stream_length,
+ "text/html");
+ g_object_unref(stream);
+}
+
+void
+mq_about_redirect(WebKitURISchemeRequest *request, const gchar *uri)
+{
+ WebKitWebView *web_view;
+
+ web_view = webkit_uri_scheme_request_get_web_view(request);
+ webkit_web_view_load_request(web_view, webkit_uri_request_new(uri));
+ mq_about_response(request, g_strdup(""));
+}
diff --git a/src/schemes/about.h b/src/schemes/about.h
new file mode 100644
index 0000000..ae224b8
--- /dev/null
+++ b/src/schemes/about.h
@@ -0,0 +1,39 @@
+/*
+ * about: URI scheme
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MQ_ABOUT_H
+#define MQ_ABOUT_H
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../application.h"
+
+void
+mq_about_request(WebKitURISchemeRequest *request, MqApplication *application);
+
+void
+mq_about_response(WebKitURISchemeRequest *request, gchar *contents);
+
+void
+mq_about_redirect(WebKitURISchemeRequest *request, const gchar *uri);
+
+#endif
diff --git a/src/schemes/about/local.mk b/src/schemes/about/local.mk
new file mode 100644
index 0000000..f2825f4
--- /dev/null
+++ b/src/schemes/about/local.mk
@@ -0,0 +1,4 @@
+marquee_SOURCES += \
+ %reldir%/version.c \
+ %reldir%/preferences.c \
+ %reldir%/marquee.c
diff --git a/src/schemes/about/marquee.c b/src/schemes/about/marquee.c
new file mode 100644
index 0000000..1ecbe08
--- /dev/null
+++ b/src/schemes/about/marquee.c
@@ -0,0 +1,74 @@
+/*
+ * about:marquee
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../../application.h"
+#include "../about.h"
+#include "../paths.h"
+
+static const gchar *document =
+ "<!doctype html>"
+ "<html dir=\"%s\">"
+ "<head>"
+ "<meta charset=\"utf-8\">"
+ "<title>%s</title>"
+ "<style>"
+ "form {"
+ "text-align: center;"
+ "}"
+ "form > input[type=submit] {"
+ "margin: 32px;"
+ "padding: 16px;"
+ "background-color: #FF0000;"
+ "color: #FFFFFF;"
+ "font-weight: bold;"
+ "font-size: 64px;"
+ "}"
+ "</style>"
+ "</head>"
+ "<body>"
+ "<form>"
+ "<input type=\"submit\" name=\"toggle\""
+ "value=\"%s\">"
+ "</form>"
+ "</body>"
+ "</html>";
+
+void
+mq_about_marquee_response(MqApplication *application, GHashTable *query,
+ WebKitURISchemeRequest *request)
+{
+ if (query && g_hash_table_lookup(query, "toggle")) {
+ if (mq_application_marquee_mode_on(application)) {
+ mq_application_marquee_mode_deactivate(application);
+ } else {
+ mq_application_marquee_mode_activate(application);
+ }
+ mq_about_redirect(request, "mq-about:marquee");
+ } else {
+ mq_about_response(request, g_strdup_printf(document,
+ gtk_widget_get_default_direction() ==
+ GTK_TEXT_DIR_RTL ? "rtl" : "ltr",
+ "DANGER", "DO NOT PRESS"));
+ }
+}
diff --git a/src/schemes/about/paths.h b/src/schemes/about/paths.h
new file mode 100644
index 0000000..1208162
--- /dev/null
+++ b/src/schemes/about/paths.h
@@ -0,0 +1,41 @@
+/*
+ * about: URI paths
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MQ_ABOUT_PATHS_H
+#define MQ_ABOUT_PATHS_H
+
+#include <glib.h>
+
+#include "../../application.h"
+
+void
+mq_about_version_response(MqApplication *application, GHashTable *query,
+ WebKitURISchemeRequest *request);
+
+void
+mq_about_preferences_response(MqApplication *application, GHashTable *query,
+ WebKitURISchemeRequest *request);
+
+void
+mq_about_marquee_response(MqApplication *application, GHashTable *query,
+ WebKitURISchemeRequest *request);
+
+#endif
diff --git a/src/schemes/about/preferences.c b/src/schemes/about/preferences.c
new file mode 100644
index 0000000..669dd62
--- /dev/null
+++ b/src/schemes/about/preferences.c
@@ -0,0 +1,260 @@
+/*
+ * about:preferences
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../../application.h"
+#include "../../config.h"
+#include "../../utils/html.h"
+#include "../about.h"
+#include "paths.h"
+
+static void
+save_pref(gchar *key, gchar *value, MqConfig *config)
+{
+ if (key[0] != '_') {
+ mq_config_set(config, key, value);
+ }
+}
+
+#define GEN_BOOL(NAME, LABEL) mq_html_input_checkbox(NAME, LABEL, \
+ mq_config_get_boolean(config, NAME))
+#define GEN_INT( NAME, LABEL, MIN, STEP, MAX) mq_html_input_number_i( \
+ NAME, LABEL, MIN, STEP, MAX, mq_config_get_integer(config, NAME))
+#define GEN_DBL( NAME, LABEL, MIN, STEP, MAX) mq_html_input_number_d( \
+ NAME, LABEL, MIN, STEP, MAX, mq_config_get_double(config, NAME))
+#define GEN_STR( NAME, LABEL) mq_html_input_text(NAME, LABEL, \
+ mq_config_get_string(config, NAME))
+#define GEN_STRL(NAME, LABEL) mq_html_input_text(NAME, LABEL, \
+ mq_config_get_string(config, NAME))
+#define GEN_SLCT(NAME, LABEL, ...) mq_html_input_select(NAME, LABEL, \
+ mq_config_get_string(config, NAME), NULL, NULL, __VA_ARGS__, NULL)
+
+static gchar *
+gen_page_general(MqConfig *config)
+{
+ return mq_html_container("div",
+ mq_html_h3("Web Browsing"),
+ GEN_SLCT("tabs.new",
+ "New Tab Page",
+ "home", "Home Page",
+ "blank", "Blank Page"),
+ GEN_STR ("tabs.home",
+ "Home Page"),
+ GEN_BOOL("tabs.background",
+ "Open New Tabs in the Background"),
+ GEN_BOOL("tabs.warn-on-close",
+ "Warn When Closing Multiple Tabs or Windows"),
+
+ mq_html_h3("Navigation and Accessibility"),
+ GEN_BOOL("navigation.smooth-scrolling",
+ "Enable Smooth Scrolling"),
+ GEN_BOOL("navigation.tabbing",
+ "Enable Tabbing Navigation (Cycling Focus by Tab Key)"),
+ GEN_BOOL("navigation.caret",
+ "Enable Caret (Text Cursor) Navigation"),
+ GEN_BOOL("navigation.spatial",
+ "Enable Spatial Navigation Between Elements By Arrow "
+ "Keys"),
+
+ mq_html_h3("Spell Checking"),
+ GEN_BOOL("spell.enable",
+ "Enable Spell Checking"),
+ GEN_STRL("spell.langs",
+ "Spell Checking Languages"),
+
+ mq_html_h3("Miscellaneous"),
+ GEN_BOOL("display.textarea.resize.enable",
+ "Enable Resizable Text Areas"),
+ GEN_BOOL("devtools.enable",
+ "Enable Developer Tools"),
+
+ mq_html_h3("Compatibility"),
+ GEN_STR ("compatibility.user-agent",
+ "User Agent Identity"),
+ GEN_BOOL("compatibility.quirks",
+ "Enable Site-Specific Quirks"),
+ NULL);
+}
+
+static gchar *
+gen_page_display(MqConfig *config)
+{
+ return mq_html_container("div",
+ mq_html_h3("Fonts"),
+ GEN_STR ("font.family.default",
+ "Default Font Family"),
+ GEN_STR ("font.family.monospace",
+ "Default Monospace Font Family"),
+ GEN_STR ("font.family.serif",
+ "Default Serif Font Family"),
+ GEN_STR ("font.family.sans-serif",
+ "Default Sans-serif Font Family"),
+ GEN_STR ("font.family.cursive",
+ "Cursive Font Family"),
+ GEN_STR ("font.family.fantasy",
+ "Fantasy Font Family"),
+ GEN_STR ("font.family.pictograph",
+ "Pictograph Font Family"),
+ GEN_INT ("font.size.default",
+ "Default Font Size", 5, 1, 72),
+ GEN_INT ("font.size.monospace-default",
+ "Default Monospace Font Size", 5, 1, 72),
+ GEN_INT ("font.size.minimum",
+ "Minimum Font Size", 0, 1, 72),
+
+ mq_html_h3("Languages"),
+ GEN_STRL("intl.accept-languages",
+ "Preferred Web Site Languages"),
+ GEN_STR ("intl.default-charset",
+ "Default Character Set"),
+
+ mq_html_h3("Zoom"),
+ GEN_DBL ("zoom.default",
+ "Default Zoom Level", 0.00, 0.10, 10.00),
+ GEN_BOOL("zoom.text-only",
+ "Zoom Text Only"),
+ NULL);
+}
+
+static gchar *
+gen_page_permissions(MqConfig *config)
+{
+ return mq_html_container("div",
+ mq_html_h3("General"),
+ GEN_BOOL("permissions.images.auto-load",
+ "Automatically Load Images"),
+ GEN_BOOL("permissions.images.favicons.override",
+ "Always Load Icons Irrespective of Automatic Image "
+ "Loading"),
+ GEN_BOOL("permissions.java.enable",
+ "Enable Java"),
+ GEN_BOOL("permissions.javascript.enable",
+ "Enable JavaScript"),
+ GEN_BOOL("permissions.plugins.enable",
+ "Enable Plugins"),
+
+ mq_html_h3("JavaScript"),
+ GEN_BOOL("permissions.javascript.open-windows",
+ "Enable JavaScript to Open Windows"),
+ GEN_BOOL("permissions.javascript.fullscreen",
+ "Enable JavaScript to Display Elements Fullscreen"),
+ GEN_BOOL("permissions.javascript.modal-dialogs",
+ "Enable JavaScript to Show Modal Dialogs"),
+ GEN_BOOL("permissions.javascript.clipboard",
+ "Enable JavaScript to Access the Clipboard"),
+
+ mq_html_h3("Data Storage"),
+ GEN_BOOL("permissions.javascript.database",
+ "Enable Web Database"),
+ GEN_BOOL("permissions.javascript.storage",
+ "Enable Web Storage"),
+ GEN_BOOL("permissions.appcache",
+ "Enable Application Cache"),
+
+ mq_html_h3("Graphics and Multimedia"),
+ GEN_BOOL("canvas.acceleration.enable",
+ "Enable Hardware-Accelerated 2-D Canvas Drawing"),
+ GEN_BOOL("permissions.javascript.webgl",
+ "Enable JavaScript WebGL 3-D Graphics Rendering"),
+ GEN_BOOL("permissions.javascript.audio",
+ "Enable JavaScript to Process and Synthesize Audio"),
+ GEN_BOOL("media.autoplay",
+ "Enable Automatic Media Playback and Loading"),
+ GEN_BOOL("media.force-fullscreen",
+ "Force Media to Play Fullscreen"),
+ GEN_BOOL("permissions.javascript.mediastream.enable",
+ "Enable JavaScript to Access Audio and Video Devices"),
+ GEN_BOOL("permissions.javascript.mediasource.enable",
+ "Enable JavaScript to Generate Media Streams"),
+ NULL);
+}
+
+static gchar *
+gen_page_sec_and_priv(MqConfig *config)
+{
+ return mq_html_container("div",
+ mq_html_h3("History"),
+ GEN_BOOL("privacy.private-browsing.enabled",
+ "Enable Private Prowsing (Disables History, Cache, and "
+ "Form Auto-Filling)"),
+ GEN_BOOL("privacy.remember.history",
+ "Remember Browsing History"),
+ GEN_BOOL("privacy.remember.downloads",
+ "Remember Download History"),
+
+ mq_html_h3("Cookies"),
+ GEN_SLCT("cookies.accept",
+ "Accept Cookies",
+ "always", "Always",
+ "never", "Never",
+ "no-third-party", "No Third-Party"),
+
+ mq_html_h3("Security"),
+ GEN_BOOL("security.xss-auditor.enable",
+ "Attempt to Detect and Block Cross-Site Scripting "
+ "Attacks"),
+
+ mq_html_h3("Network"),
+ GEN_BOOL("dns.prefetch.enable",
+ "Prefetch Domain Name Resolutions for Better "
+ "Performance"),
+ NULL);
+}
+
+#undef GEN_BOOL
+#undef GEN_INT
+#undef GEN_DBL
+#undef GEN_STR
+#undef GEN_STRL
+
+void
+mq_about_preferences_response(MqApplication *application, GHashTable *query,
+ WebKitURISchemeRequest *request)
+{
+ MqConfig *config;
+ gchar *document;
+
+ config = mq_application_get_config(application);
+
+ if (query) {
+ g_hash_table_foreach(query, (GHFunc) save_pref, config);
+ mq_config_save(config);
+ mq_about_redirect(request, "mq-about:preferences");
+ } else {
+ document = mq_html_document("Preferences",
+ mq_html_form("Save", "Cancel",
+ mq_html_notebook(FALSE, "notebook1", 0,
+ gen_page_general(config),
+ "General",
+ gen_page_display(config),
+ "Display",
+ gen_page_permissions(config),
+ "Permissions",
+ gen_page_sec_and_priv(config),
+ "Security and Privacy",
+ NULL),
+ NULL),
+ NULL);
+ mq_about_response(request, document);
+ }
+}
diff --git a/src/schemes/about/version.c b/src/schemes/about/version.c
new file mode 100644
index 0000000..8045ade
--- /dev/null
+++ b/src/schemes/about/version.c
@@ -0,0 +1,73 @@
+/*
+ * about:version
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../../application.h"
+#include "../../utils/html.h"
+#include "../about.h"
+#include "paths.h"
+
+extern const char *PACKAGE_VERSION_GIT;
+
+void
+mq_about_version_response(MqApplication G_GNUC_UNUSED *application,
+ GHashTable G_GNUC_UNUSED *query,
+ WebKitURISchemeRequest *request)
+{
+ gchar *title;
+ gchar *document;
+
+ title = g_strdup_printf("About %s", PACKAGE_NAME);
+ document = mq_html_document(title,
+ mq_html_notebook(FALSE, "notebook1", 0,
+ mq_html_container("div",
+ mq_html_h3(PACKAGE_NAME),
+ mq_html_p_free(g_strconcat(PACKAGE_VERSION,
+ PACKAGE_VERSION_GIT, NULL)),
+ /* TODO: Comments */
+ /* TODO: Web site link */
+ mq_html_p("Copyright &copy; 2017 "
+ "Patrick McDermott"),
+ mq_html_p("This program comes with "
+ "ABSOLUTELY NO WARRANTY. "
+ "See the license text for details."),
+ NULL),
+ "About",
+ mq_html_container("div",
+ mq_html_h3("Authors"),
+ mq_html_p("Patrick McDermott "
+ "&lt;pj@pehjota.net&gt;"),
+ NULL),
+ "Credits",
+ mq_html_input_iframe("mq-about:resources/"
+ "gpl-3.0-standalone.html"),
+ "License",
+ NULL),
+ NULL);
+ g_free(title);
+ mq_about_response(request, document);
+}
diff --git a/src/schemes/view-source.c b/src/schemes/view-source.c
new file mode 100644
index 0000000..b6cce86
--- /dev/null
+++ b/src/schemes/view-source.c
@@ -0,0 +1,150 @@
+/*
+ * view-source: URI scheme
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "view-source.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../application.h"
+#include "../utils/resources.h"
+#include "../utils/string.h"
+
+typedef struct {
+ WebKitURISchemeRequest *request;
+ gchar *uri;
+ gulong handler_id;
+} DataSignalData;
+
+static const gchar *document =
+ "<!doctype html>\n"
+ "<html dir=\"%s\">\n"
+ "<head>\n"
+ "<meta charset=\"utf-8\">\n"
+ "<title>Source of %s</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "media=\"all\" "
+ "href=\"view-source:resources/prism/"
+ "prism.css\">\n"
+ "<script src=\"view-source:resources/prism/"
+ "prism.js\"></script>\n"
+ "</head>\n"
+ "<body style=\"margin: 0;\">\n"
+ "<pre style=\"overflow: visible; width: 100%; "
+ "margin: 0;\">\n"
+ "<code class=\"language-markup line-numbers\" "
+ "style=\"overflow: visible;\">"
+ "%s</code>\n"
+ "</pre>\n"
+ "</body>\n"
+ "</html>\n";
+
+static void
+respond(WebKitURISchemeRequest *request, const gchar *uri, guchar *data,
+ gsize length)
+{
+ gchar *escaped_data;
+ GInputStream *stream;
+
+ escaped_data = g_markup_escape_text((gchar *) data, length);
+
+ stream = g_memory_input_stream_new_from_data(
+ g_strdup_printf(document,
+ gtk_widget_get_default_direction() ==
+ GTK_TEXT_DIR_RTL ? "rtl" : "ltr",
+ uri, escaped_data), -1, g_free);
+
+ webkit_uri_scheme_request_finish(request, stream, -1, "text/html");
+ g_object_unref(stream);
+}
+
+static void
+data_cb(MqWebView *web_view, GParamSpec G_GNUC_UNUSED *param_spec,
+ DataSignalData *data_signal_data)
+{
+ guchar *data;
+ gsize length;
+
+ data = mq_web_view_get_data(web_view, &length);
+ respond(data_signal_data->request, data_signal_data->uri, data, length);
+ g_signal_handler_disconnect(web_view, data_signal_data->handler_id);
+ g_free(data_signal_data->uri);
+ g_free(data_signal_data);
+}
+
+void
+mq_view_source_request(WebKitURISchemeRequest *request,
+ MqApplication *application)
+{
+ const gchar *path;
+ gchar *query_str;
+ GHashTable *query;
+ gint64 origin_tab_id;
+ gchar *uri;
+ MqTabPage *origin_tab;
+ MqWebView *origin_web_view;
+ guchar *data;
+ gsize length;
+ DataSignalData *data_signal_data;
+
+ path = webkit_uri_scheme_request_get_path(request);
+
+ if (g_str_has_prefix(path, "resources/")) {
+ mq_resource_response(application, path + sizeof("resources"),
+ request);
+ return;
+ }
+
+ query_str = g_strdup(path);
+ query = mq_parse_query_string(query_str);
+
+ /* TODO: Handle missing tab ID ("origin-tab=0"). */
+ origin_tab_id = mq_atoi64(g_hash_table_lookup(query, "origin-tab"));
+ uri = g_strdup(g_hash_table_lookup(query, "uri"));
+
+ g_hash_table_unref(query);
+ g_free(query_str);
+
+ origin_tab = mq_application_get_tab(application, origin_tab_id);
+
+ if (origin_tab) {
+ origin_web_view = mq_tab_page_get_web_view(origin_tab);
+
+ data = mq_web_view_get_data(origin_web_view, &length);
+ if (data) {
+ respond(request, uri, data, length);
+ } else {
+ data_signal_data = g_new(DataSignalData, 1);
+ data_signal_data->request = request;
+ data_signal_data->uri = uri;
+ data_signal_data->handler_id = g_signal_connect(
+ origin_web_view, "notify::data",
+ G_CALLBACK(data_cb), data_signal_data);
+ }
+ } else {
+ /* TODO: Handling reloads by newly requesting the resource
+ * should obviate this. */
+ respond(request, uri,
+ (guchar *) g_strdup("Viewed tab no longer open"), -1);
+ }
+}
diff --git a/src/schemes/view-source.h b/src/schemes/view-source.h
new file mode 100644
index 0000000..1f948e5
--- /dev/null
+++ b/src/schemes/view-source.h
@@ -0,0 +1,34 @@
+/*
+ * view-source: URI scheme
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee 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 Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MQ_VIEW_SOURCE_H
+#define MQ_VIEW_SOURCE_H
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../application.h"
+
+void
+mq_view_source_request(WebKitURISchemeRequest *request,
+ MqApplication *application);
+
+#endif /* MQ_VIEW_SOURCE_H */