surf

surf browser, a WebKit based browser
git clone git://git.suckless.org/surf
Log | Files | Refs | README | LICENSE

webext-surf.c (3687B)


      1 #include <sys/socket.h>
      2 #include <sys/stat.h>
      3 #include <fcntl.h>
      4 #include <inttypes.h>
      5 #include <limits.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 
      9 #include <gio/gio.h>
     10 #include <gio/gunixfdlist.h>
     11 #include <webkit2/webkit-web-extension.h>
     12 #include <webkitdom/webkitdom.h>
     13 #include <webkitdom/WebKitDOMDOMWindowUnstable.h>
     14 
     15 #include "common.h"
     16 
     17 #define LENGTH(x)   (sizeof(x) / sizeof(x[0]))
     18 
     19 static WebKitWebExtension *webext;
     20 static int sock;
     21 
     22 /*
     23  * Return:
     24  * 0 No data processed: need more data
     25  * > 0 Amount of data processed or discarded
     26  */
     27 static size_t
     28 evalmsg(char *msg, size_t sz)
     29 {
     30 	char js[48];
     31 	WebKitWebPage *page;
     32 	JSCContext *jsc;
     33 	JSCValue *jsv;
     34 
     35 	if (!(page = webkit_web_extension_get_page(webext, msg[0])))
     36 		return sz;
     37 
     38 	if (sz < 2)
     39 		return 0;
     40 
     41 	jsc = webkit_frame_get_js_context(webkit_web_page_get_main_frame(page));
     42 	jsv = NULL;
     43 
     44 	switch (msg[1]) {
     45 	case 'h':
     46 		if (sz < 3) {
     47 			sz = 0;
     48 			break;
     49 		}
     50 		sz = 3;
     51 		snprintf(js, sizeof(js),
     52 		         "window.scrollBy(window.innerWidth/100*%hhd,0);",
     53 		         msg[2]);
     54 		jsv = jsc_context_evaluate(jsc, js, -1);
     55 		break;
     56 	case 'v':
     57 		if (sz < 3) {
     58 			sz = 0;
     59 			break;
     60 		}
     61 		sz = 3;
     62 		snprintf(js, sizeof(js),
     63 		         "window.scrollBy(0,window.innerHeight/100*%hhd);",
     64 		         msg[2]);
     65 		jsv = jsc_context_evaluate(jsc, js, -1);
     66 		break;
     67 	default:
     68 		fprintf(stderr, "%s:%d:evalmsg: unknown cmd(%zu): '%#x'\n",
     69 		        __FILE__, __LINE__, sz, msg[1]);
     70 	}
     71 
     72 	g_object_unref(jsc);
     73 	if (jsv)
     74 		g_object_unref(jsv);
     75 
     76 	return sz;
     77 }
     78 
     79 static gboolean
     80 readsock(GIOChannel *s, GIOCondition c, gpointer unused)
     81 {
     82 	static char msg[MSGBUFSZ];
     83 	static size_t msgoff;
     84 	GError *gerr = NULL;
     85 	size_t sz;
     86 	gsize rsz;
     87 
     88 	if (g_io_channel_read_chars(s, msg+msgoff, sizeof(msg)-msgoff, &rsz, &gerr) !=
     89 	    G_IO_STATUS_NORMAL) {
     90 		if (gerr) {
     91 			fprintf(stderr, "webext: error reading socket: %s\n",
     92 			        gerr->message);
     93 			g_error_free(gerr);
     94 		}
     95 		return TRUE;
     96 	}
     97 	if (msgoff >= sizeof(msg)) {
     98 		fprintf(stderr, "%s:%d:%s: msgoff: %zu", __FILE__, __LINE__, __func__, msgoff);
     99 		return FALSE;
    100 	}
    101 
    102 	for (rsz += msgoff; rsz; rsz -= sz) {
    103 		sz = evalmsg(msg, rsz);
    104 		if (sz == 0) {
    105 			/* need more data */
    106 			break;
    107 		}
    108 		if (sz != rsz) {
    109 			/* continue processing message */
    110 			memmove(msg, msg+sz, rsz-sz);
    111 		}
    112 	}
    113 	msgoff = rsz;
    114 
    115 	return TRUE;
    116 }
    117 
    118 static void
    119 pageusermessagereply(GObject *o, GAsyncResult *r, gpointer page)
    120 {
    121 	WebKitUserMessage *m;
    122 	GUnixFDList *gfd;
    123 	GIOChannel *gchansock;
    124 	const char *name;
    125 	int nfd;
    126 
    127 	m = webkit_web_page_send_message_to_view_finish(page, r, NULL);
    128 	name = webkit_user_message_get_name(m);
    129 	if (strcmp(name, "surf-pipe") != 0) {
    130 		fprintf(stderr, "webext-surf: Unknown User Reply: %s\n", name);
    131 		return;
    132 	}
    133 
    134 	gfd = webkit_user_message_get_fd_list(m);
    135 	if ((nfd = g_unix_fd_list_get_length(gfd)) != 1) {
    136 		fprintf(stderr, "webext-surf: Too many file-descriptors: %d\n", nfd);
    137 		return;
    138 	}
    139 
    140 	sock = g_unix_fd_list_get(gfd, 0, NULL);
    141 
    142 	gchansock = g_io_channel_unix_new(sock);
    143 	g_io_channel_set_encoding(gchansock, NULL, NULL);
    144 	g_io_channel_set_flags(gchansock, g_io_channel_get_flags(gchansock)
    145 	                       | G_IO_FLAG_NONBLOCK, NULL);
    146 	g_io_channel_set_close_on_unref(gchansock, TRUE);
    147 	g_io_add_watch(gchansock, G_IO_IN, readsock, NULL);
    148 }
    149 
    150 void
    151 pagecreated(WebKitWebExtension *e, WebKitWebPage *p, gpointer unused)
    152 {
    153 	WebKitUserMessage *msg;
    154 
    155 	msg = webkit_user_message_new("page-created", NULL);
    156 	webkit_web_page_send_message_to_view(p, msg, NULL, pageusermessagereply, p);
    157 }
    158 
    159 G_MODULE_EXPORT void
    160 webkit_web_extension_initialize(WebKitWebExtension *e)
    161 {
    162 	webext = e;
    163 
    164 	g_signal_connect(G_OBJECT(e), "page-created",
    165 	                 G_CALLBACK(pagecreated), NULL);
    166 }