merge holizz' scheme handler
authorDieter Plaetinck <dieter@plaetinck.be>
Tue, 25 Aug 2009 20:21:20 +0000 (22:21 +0200)
committerDieter Plaetinck <dieter@plaetinck.be>
Tue, 25 Aug 2009 20:21:20 +0000 (22:21 +0200)
README
examples/config/uzbl/config
examples/data/uzbl/scripts/scheme.py [new file with mode: 0755]
uzbl.c
uzbl.h

diff --git a/README b/README
index b36293c..fe92bcf 100644 (file)
--- a/README
+++ b/README
@@ -200,6 +200,7 @@ Besides the builtin variables you can also define your own ones and use them in
   - download_handler
   - cookie_handler
   - new_window: handler to execute to invoke new uzbl window (TODO better name)
+  - scheme_handler: handler to execute for each URI navigated to - the navigation request will be ignored if handler prints "USED\n"
   - fifo_dir: location to store fifo's
   - socket_dir: location to store sockets
   - http_debug: http debug mode (value 0-3)
@@ -373,6 +374,10 @@ The script specific arguments are this:
     $11 request address path
     $12 cookie (only with PUT requests)
 
+* scheme handler:
+
+    $8 URI of the page to be navigated to
+
 
 Custom, userdefined scripts (`spawn foo bar`) get first the arguments as specified in the config and then the above 7 are added at the end.
 
index ab2cf7f..04e482b 100644 (file)
@@ -9,6 +9,7 @@ set download_handler = spawn $XDG_DATA_HOME/uzbl/scripts/download.sh
 set cookie_handler   = spawn $XDG_DATA_HOME/uzbl/scripts/cookies.py
 #set new_window      = sh 'echo uri "$8" > $4' # open in same window
 set new_window       = sh 'uzbl -u $8' # equivalent to the default behaviour
+set scheme_handler   = spawn $XDG_DATA_HOME/uzbl/scripts/scheme.py
 set load_start_handler = set status_message = <span foreground="khaki">wait</span>
 set load_commit_handler = set status_message = <span foreground="green">recv</span>
 set load_finish_handler = set status_message = <span foreground="gold">done</span>
diff --git a/examples/data/uzbl/scripts/scheme.py b/examples/data/uzbl/scripts/scheme.py
new file mode 100755 (executable)
index 0000000..7286703
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+import os, subprocess, sys, urlparse
+
+def detach_open(cmd):
+    # Thanks to the vast knowledge of Laurence Withers (lwithers) and this message:
+    # http://mail.python.org/pipermail/python-list/2006-November/587523.html
+    if not os.fork():
+        null = os.open(os.devnull,os.O_WRONLY)
+        for i in range(3): os.dup2(null,i)
+        os.close(null)
+        subprocess.Popen(cmd)
+    print 'USED'
+
+if __name__ == '__main__':
+    uri = sys.argv[8]
+    u = urlparse.urlparse(uri)
+    if u.scheme == 'mailto':
+        detach_open(['xterm', '-e', 'mail %s' % u.path])
+    elif u.scheme == 'xmpp':
+        detach_open(['gajim-remote', 'open_chat', uri])
+    elif u.scheme == 'git':
+        detach_open(['git', 'clone', uri], cwd=os.path.expanduser('~/src'))
diff --git a/uzbl.c b/uzbl.c
index e90d220..8de3faf 100644 (file)
--- a/uzbl.c
+++ b/uzbl.c
@@ -140,7 +140,8 @@ const struct var_name_to_ptr_t {
     { "history_handler",        PTR_V_STR(uzbl.behave.history_handler,          1,   NULL)},
     { "download_handler",       PTR_V_STR(uzbl.behave.download_handler,         1,   NULL)},
     { "cookie_handler",         PTR_V_STR(uzbl.behave.cookie_handler,           1,   cmd_cookie_handler)},
-    { "new_window",             PTR_V_STR(uzbl.behave.new_window,               1,   cmd_new_window)},
+    { "new_window",             PTR_V_STR(uzbl.behave.new_window,               1,   NULL)},
+    { "scheme_handler",         PTR_V_STR(uzbl.behave.scheme_handler,           1,   cmd_scheme_handler)},
     { "fifo_dir",               PTR_V_STR(uzbl.behave.fifo_dir,                 1,   cmd_fifo_dir)},
     { "socket_dir",             PTR_V_STR(uzbl.behave.socket_dir,               1,   cmd_socket_dir)},
     { "http_debug",             PTR_V_INT(uzbl.behave.http_debug,               1,   cmd_http_debug)},
@@ -510,6 +511,44 @@ catch_sigint(int s) {
 /* --- CALLBACKS --- */
 
 gboolean
+navigation_decision_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
+    (void) web_view;
+    (void) frame;
+    (void) navigation_action;
+    (void) user_data;
+
+    const gchar* uri = webkit_network_request_get_uri (request);
+    gboolean decision_made = FALSE;
+
+    if (uzbl.state.verbose)
+        printf("Navigation requested -> %s\n", uri);
+
+    if (uzbl.behave.scheme_handler) {
+        GString *s = g_string_new ("");
+        g_string_printf(s, "'%s'", uri);
+
+        run_handler(uzbl.behave.scheme_handler, s->str);
+
+        if(uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) {
+            char *p = strchr(uzbl.comm.sync_stdout, '\n' );
+            if ( p != NULL ) *p = '\0';
+            if (!strcmp(uzbl.comm.sync_stdout, "USED")) {
+                webkit_web_policy_decision_ignore(policy_decision);
+                decision_made = TRUE;
+            }
+        }
+        if (uzbl.comm.sync_stdout)
+            uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
+
+        g_string_free(s, TRUE);
+    }
+    if (!decision_made)
+        webkit_web_policy_decision_use(policy_decision);
+
+    return TRUE;
+}
+
+gboolean
 new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data) {
     (void) web_view;
     (void) frame;
@@ -951,7 +990,7 @@ load_uri (WebKitWebView *web_view, GArray *argv, GString *result) {
             run_js(web_view, argv, NULL);
             return;
         }
-        if (g_strrstr (argv_idx(argv, 0), "://") == NULL && g_strstr_len (argv_idx(argv, 0), 5, "data:") == NULL)
+        if (!soup_uri_new(argv_idx(argv, 0)))
             g_string_prepend (newuri, "http://");
         /* if we do handle cookies, ask our handler for them */
         webkit_web_view_load_uri (web_view, newuri->str);
@@ -1759,14 +1798,14 @@ cmd_cookie_handler() {
 }
 
 void
-cmd_new_window() {
-    gchar **split = g_strsplit(uzbl.behave.new_window, " ", 2);
+cmd_scheme_handler() {
+    gchar **split = g_strsplit(uzbl.behave.scheme_handler, " ", 2);
     /* pitfall: doesn't handle chain actions; must the sync_ action manually */
     if ((g_strcmp0(split[0], "sh") == 0) ||
         (g_strcmp0(split[0], "spawn") == 0)) {
-        g_free (uzbl.behave.new_window);
-        uzbl.behave.new_window =
-            g_strdup_printf("%s %s", split[0], split[1]);
+        g_free (uzbl.behave.scheme_handler);
+        uzbl.behave.scheme_handler =
+            g_strdup_printf("sync_%s %s", split[0], split[1]);
     }
     g_strfreev (split);
 }
@@ -2321,6 +2360,7 @@ create_browser () {
     g_signal_connect (G_OBJECT (g->web_view), "load-finished", G_CALLBACK (log_history_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "load-finished", G_CALLBACK (load_finish_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), g->web_view);
+    g_signal_connect (G_OBJECT (g->web_view), "navigation-policy-decision-requested", G_CALLBACK (navigation_decision_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "new-window-policy-decision-requested", G_CALLBACK (new_window_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "download-requested", G_CALLBACK (download_cb), g->web_view);
     g_signal_connect (G_OBJECT (g->web_view), "create-web-view", G_CALLBACK (create_web_view_cb), g->web_view);
@@ -2858,6 +2898,7 @@ main (int argc, char* argv[]) {
             printf("window_id %i\n",(int) uzbl.xwin);
         printf("pid %i\n", getpid ());
         printf("name: %s\n", uzbl.state.instance_name);
+        printf("commit: %s\n", uzbl.info.commit);
     }
 
     uzbl.gui.scbar_v = (GtkScrollbar*) gtk_vscrollbar_new (NULL);
diff --git a/uzbl.h b/uzbl.h
index 658eae4..780aebf 100644 (file)
--- a/uzbl.h
+++ b/uzbl.h
@@ -105,6 +105,7 @@ typedef struct {
     gchar*   serif_font_family;
     gchar*   fantasy_font_family;
     gchar*   cursive_font_family;
+    gchar*   scheme_handler;
     gboolean always_insert_mode;
     gboolean show_status;
     gboolean insert_mode;
@@ -227,6 +228,9 @@ void
 print(WebKitWebView *page, GArray *argv, GString *result);
 
 gboolean
+navigation_decision_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data);
+
+gboolean
 new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data);
 
 gboolean
@@ -488,7 +492,7 @@ void
 cmd_cookie_handler();
 
 void
-cmd_new_window();
+cmd_scheme_handler();
 
 void
 move_statusbar();