libsurf-webext.c (2835B)
1 #include <sys/stat.h> 2 #include <fcntl.h> 3 #include <limits.h> 4 #include <stdlib.h> 5 6 #include <gio/gio.h> 7 #include <webkit2/webkit-web-extension.h> 8 #include <webkitdom/webkitdom.h> 9 #include <webkitdom/WebKitDOMDOMWindowUnstable.h> 10 11 #include "common.h" 12 13 #define LENGTH(x) (sizeof(x) / sizeof(x[0])) 14 15 typedef struct Page { 16 guint64 id; 17 WebKitWebPage *webpage; 18 struct Page *next; 19 } Page; 20 21 static int pipein, pipeout; 22 static Page *pages; 23 24 Page * 25 newpage(WebKitWebPage *page) 26 { 27 Page *p; 28 29 if (!(p = calloc(1, sizeof(Page)))) 30 die("Cannot malloc!\n"); 31 32 p->next = pages; 33 pages = p; 34 35 p->id = webkit_web_page_get_id(page); 36 p->webpage = page; 37 38 return p; 39 } 40 41 static void 42 msgsurf(Page *p, const char *s) 43 { 44 static char msg[MSGBUFSZ]; 45 size_t sln = strlen(s); 46 int ret; 47 48 if ((ret = snprintf(msg, sizeof(msg), "%c%c%s", 49 2 + sln, p ? p->id : 0, s)) 50 >= sizeof(msg)) { 51 fprintf(stderr, "webext: message too long: %d\n", ret); 52 return; 53 } 54 55 if (pipeout && write(pipeout, msg, sizeof(msg)) < 0) 56 fprintf(stderr, "webext: error sending: %.*s\n", ret-2, msg+2); 57 } 58 59 static gboolean 60 readpipe(GIOChannel *s, GIOCondition c, gpointer unused) 61 { 62 static char msg[MSGBUFSZ], msgsz; 63 WebKitDOMDOMWindow *view; 64 GError *gerr = NULL; 65 glong wh, ww; 66 Page *p; 67 68 if (g_io_channel_read_chars(s, msg, LENGTH(msg), NULL, &gerr) != 69 G_IO_STATUS_NORMAL) { 70 fprintf(stderr, "webext: error reading pipe: %s\n", 71 gerr->message); 72 g_error_free(gerr); 73 return TRUE; 74 } 75 if ((msgsz = msg[0]) < 3) { 76 fprintf(stderr, "webext: message too short: %d\n", msgsz); 77 return TRUE; 78 } 79 80 for (p = pages; p; p = p->next) { 81 if (p->id == msg[1]) 82 break; 83 } 84 if (!p || !(view = webkit_dom_document_get_default_view( 85 webkit_web_page_get_dom_document(p->webpage)))) 86 return TRUE; 87 88 switch (msg[2]) { 89 case 'h': 90 if (msgsz != 4) 91 return TRUE; 92 ww = webkit_dom_dom_window_get_inner_width(view); 93 webkit_dom_dom_window_scroll_by(view, 94 (ww / 100) * msg[3], 0); 95 break; 96 case 'v': 97 if (msgsz != 4) 98 return TRUE; 99 wh = webkit_dom_dom_window_get_inner_height(view); 100 webkit_dom_dom_window_scroll_by(view, 101 0, (wh / 100) * msg[3]); 102 break; 103 } 104 105 return TRUE; 106 } 107 108 static void 109 webpagecreated(WebKitWebExtension *e, WebKitWebPage *wp, gpointer unused) 110 { 111 Page *p = newpage(wp); 112 } 113 114 G_MODULE_EXPORT void 115 webkit_web_extension_initialize_with_user_data(WebKitWebExtension *e, GVariant *gv) 116 { 117 GIOChannel *gchanpipe; 118 119 g_signal_connect(e, "page-created", G_CALLBACK(webpagecreated), NULL); 120 121 g_variant_get(gv, "(ii)", &pipein, &pipeout); 122 msgsurf(NULL, "i"); 123 124 gchanpipe = g_io_channel_unix_new(pipein); 125 g_io_channel_set_encoding(gchanpipe, NULL, NULL); 126 g_io_channel_set_close_on_unref(gchanpipe, TRUE); 127 g_io_add_watch(gchanpipe, G_IO_IN, readpipe, NULL); 128 }